Dieser Artikel beschreibt einen der Ansätze für die nächste Entwicklungsstufe von OOP (objektorientierte Programmierung). Der klassische Ansatz für OOP basiert auf dem Konzept der Vererbung, das wiederum die Verwendung und Änderung von vorgefertigtem Code stark einschränkt. Beim Erstellen neuer Klassen ist es nicht immer möglich, von vorhandenen Klassen zu erben (das Problem der rautenförmigen Vererbung) oder vorhandene Klassen zu ändern, von denen viele andere Klassen bereits geerbt haben (eine fragile (oder übermäßig aufgeblähte) Basisklasse). Bei der Entwicklung der Programmiersprache Delight wurde ein alternativer Ansatz für die Arbeit mit Klassen und deren Zusammensetzung gewählt - CPC (Component-Oriented Programming).
Auf den Punkt
, . , . , , . , - , .
, . . .
class BaseBehavior
unitPos: UnitPos [shared]
fn DoTurn [virtual]
class PathBuilder
unitPos: UnitPos [shared]
fn Moving:boolean [virtual]
...
fn BuildPath(x:int, y:int) [virtual]
...
// ... and some more helper functions ...
BaseBehavior - , , .
PathBuilder - ( ).
[shared] .
, :
class SimpleBehavior
base: BaseBehavior [shared]
path: PathBuilder [shared]
fne DoTurn // override of BaseBehavior.DoTurn
if path.Moving = false
path.BuildRandomPath
class AgressiveBehavior
open SimpleBehavior [shared]
fne DoTurn // override of SimpleBehavior.DoTurn
d: float = path.GetDistance(player.x, player.y) // get distance from this unit to player
if d < 30
path.BuildPath(player.x, player.y) // run to player
else
nextFn // inherited call to next DoTurn
class ScaredBehavior
open SimpleBehavior [shared]
fne DoTurn // override of SimpleBehavior.DoTurn
d: float = path.GetDistance(player.x, player.y) // get distance from this unit to player
if d < 50
path.BuildPathAwayFrom(player.x, player.y) // run away from player
else
nextFn // inherited call to next DoTurn
:
SimpleBehavior - .
AgressiveBehavior - , . SimpleBehavior.
ScaredBehavior - , SimpleBehavior.
open - .
fne - (override) .
nextFn - .
, :
class UncertainBehavior
open AgressiveBehavior [shared]
open ScaredBehavior [shared]
"" . , DoTurn, AgressiveBehavior.DoTurn. , . , ScaredBehavior.DoTurn - , . , SimpleBehavior.DoTurn .
(AgressiveBehavior), (ScaredBehavior) (UncertainBehavior). ? ? ? . . :
class PathBuilder_air //
path: PathBuilder [shared]
fne BuildPath(x:int, y:int)
...
class PathBuilder_water //
path: PathBuilder [shared]
fne BuildPath(x:int, y:int)
...
:
class Shark
open PathBuilder_water [shared]
open AgressiveBehavior [shared]
"", , AgressiveBehavior, , PathBuilder (shared), AgressiveBehavior ( SimpleBehavior) PathBuilder_water ( PathBuilder). AgressiveBehavior , . , - , :
class Fish
open PathBuilder_water [shared]
open ScaredBehavior [shared]
class Eagle
open PathBuilder_air [shared]
open UncertainBehavior [shared]
class Pigeon
open PathBuilder_air [shared]
open ScaredBehavior [shared]
class Wolf
open AgressiveBehavior [shared]
, - - -.
Delight
Delight :
class NonVirtualClass
val: OtherClass
fn SomeFn
Trace('Hello world')
val , OtherClass.
, , [virtual]
fn SomeFn [virtual]
Trace('Hello virtual world')
/ fne ( fn)
fne SomeFn
Trace('Hello overrided world')
( ) . , , [shared] (), fne :
class BaseClass
fn SomeFn [virtual]
Trace('Hello virtual world')
class NewClass
base: BaseClass [shared]
fne SomeFn
Trace('Hello overrided world')
nextFn
nextFn .
( ) ++
class BaseClass
{
public:
virtual void SomeFn()
{
Trace('Hello virtual world');
}
};
class NewClass : public virtual BaseClass
{
virtual void SomeFn() override
{
Trace('Hello overrided world');
BaseClass::SomeFn();
}
};
[shared], . , shared , , [shared] , , [shared] ( vtable).
:
class Base
val: int
class ClsA
base: Base [shared]
class ClsB
base: Base [shared]
class ClsC
a: ClsA [shared]
b: ClsB [shared]
ClsC, (Base, ClsA, ClsB) val () . , ++.
, ( , , ), . Delight open ( ). , ( this).
class ClsA
open Base [shared]
fne Constructor
val = 10
, . , :
, (shared) , ;
(shared) , .
, :
, ;
.
, nextFn. , (virtual call), (inherited call).
, :
class Base
fn SomeVirtFn [virtual]
Trace('Base')
class ClsA
open Base [shared]
fne SomeVirtFn
Trace('ClsA')
class ClsB
open Base [shared]
fne SomeVirtFn
Trace('ClsB')
class ClsC
open ClsA [shared]
open ClsB [shared]
fne SomeVirtFn
Trace('ClsC')
....
fn Main
c: ClsC
c.SomeVirtFn
:
ClsC
ClsA
ClsB
Base
Mit diesem Ansatz können Sie Funktionen einer Klasse mit einer anderen überladen, während Sie sich auf derselben Hierarchieebene befinden. Dank dessen können Klassen aus vorgefertigten Komponenten bestehen, die die Funktionen anderer Personen überlappen oder ergänzen, was die Komposition des Codes erheblich erleichtert. Während der Komposition wird die Hauptfunktionalität der Abschlussklasse in mehrere Grundbausteine unterteilt, deren Kombination die gewünschten Ergebnisse liefert. Delight unterstützt auch die statische Code-Komposition, dies ist jedoch bereits Material für einen anderen Artikel.