Komposisi alih-alih warisan dalam bahasa pemrograman Delight

Artikel ini membahas salah satu pendekatan untuk tahap selanjutnya pengembangan OOP (pemrograman berorientasi objek). Pendekatan klasik untuk OOP didasarkan pada konsep pewarisan, yang pada gilirannya memberlakukan pembatasan serius pada penggunaan dan modifikasi kode yang sudah jadi. Saat membuat kelas baru, tidak selalu mungkin untuk mewarisi dari kelas yang sudah ada (masalah warisan berbentuk berlian ) atau memodifikasi kelas yang sudah ada yang sudah diwarisi oleh banyak kelas lain (kelas dasar yang rapuh (atau terlalu membengkak)). Saat mengembangkan bahasa pemrograman Delight, pendekatan alternatif dipilih untuk bekerja dengan kelas dan komposisinya - BPK (pemrograman berorientasi komponen).





Langsung ke intinya

Kita harus mulai dengan dasar-dasar bahasa, sintaksisnya, dan aturan BPK. Tapi ini cukup membosankan, jadi mari kita langsung ke contoh game tertentu. Untuk memahami semua hal berikut, diperlukan pengetahuan penuh tentang OOP, karena komposisinya sendiri dibangun di atas prinsip yang sama dengan OOP. Rincian lebih lanjut tentang cara kerjanya dapat ditemukan di bagian selanjutnya setelah ini.





Mari kita pertimbangkan contoh dari permainan bersyarat di mana beberapa makhluk dapat bergerak di sekitar peta. Mari kita tulis kode untuk perilaku makhluk-makhluk ini. Mari kita mulai dengan kelas dasar.





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 - bertanggung jawab atas perilaku dasar makhluk, kelas itu sendiri tidak memiliki logika, hanya deklarasi yang diperlukan.





PathBuilder adalah kelas yang bertanggung jawab untuk menemukan jalur di sepanjang tanah (termasuk menghindari rintangan).





Pengubah [bersama] berarti bahwa bidang ini akan dibagikan oleh semua subkelas dari kelas akhir.





, :





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
      
      



Pendekatan ini memungkinkan Anda untuk membebani fungsi dari satu kelas dengan kelas lainnya, sambil berada pada tingkat hierarki yang sama. Berkat ini, kelas dapat terdiri dari komponen siap pakai yang tumpang tindih atau melengkapi fungsi orang lain, yang sangat memudahkan komposisi kode. Selama komposisi, fungsionalitas utama dari kelas akhir dipecah menjadi beberapa blok bangunan dasar, yang kombinasinya memberikan hasil yang diinginkan. Delight juga mendukung komposisi kode statis, tetapi ini sudah menjadi bahan untuk artikel lain.








All Articles