Простое наследование

С версии компилятора 0.24, у программистов на языке Freebasic появилась возможность использовать в текстах своих программ простое наследование. Данная возможность дает некоторое сокращение кода в больших программах и делает код , скажем так , более современным...

Чаще всего данную возможность применяют в создании игр. Я попробую показать это на простом примере. К примеру у вас в игре есть три типа объектов: планеты, астероиды, корабли. Каждый из этих объектов имеет некоторые одинаковые свойства и методы:

Type SharedType
    ID As Integer ' идентификатор объекта
    Handle As Any Ptr ' хендл изображения
    Width_  As Integer ' ширина объекта
    Height As Integer ' высота объекта
    Declare Constructor() ' инициализация объекта
    Declare Destructor() ' деинициализация объекта
    Declare Sub Explosion() ' взрыв объекта
End Type

Constructor SharedType()
    ' инициализация всех свойств объекта
End Constructor

Destructor SharedType()
    'подчищение всех данных объекта
End Destructor

Sub SharedType.Explosion()
    'реализация взрыва
End Sub

Однако каждый из этих объектов может иметь свои отдельные свойства и методы, которые реализуются в своем отдельном классе. Этот класс будет потомком от класса SharedType и будет наследовать все его свойства и методы. В итоге кроме своих собственных ресурсов, потомок может пользоваться и ресурсами родителя. С другой стороны родителю закрыт доступ к ресурсам потомка. Так например маленький ребенок может надеть одежду родителя, но родитель в одежду ребенка просто не влезет :)

Но если возвратиться к объектам, планеты могут вращаться , иметь оружие и радары, но скажем в игре не могут перемещаться. Астероиды могут перемещаться, но не имеют ни оружия , ни радаров. А корабли могут и имеют все перечисленное. Эта разность как раз и подталкивает к созданию наследуемых классов:

' Класс планет
Type Planets Extends SharedType
    IDRadar As Integer ' идентификатор радара
   IDWeapon As Integer ' идентификатор оружия
    Declare Sub Rotate()
End Type

' Класс астероидов
Type Asteroids Extends SharedType
    Declare Sub Move()
End Type

' Класс кораблей
Type Ships Extends SharedType
    IDRadar As Integer
   IDWeapon As Integer
    Declare Sub Rotate()
    Declare Sub Move()
End Type

' метод вращения планет
Sub Planets.Rotate()
    
End Sub

' метод движения астероидов 
Sub Asteroids.Move()
    
End Sub

' метод вращения кораблей
Sub Ships.Rotate()
    
End Sub

' метод движения кораблей
Sub Ships.Move()
    
End Sub

Как можно заметить в Freebasic появилось новое ключевое слово EXTENDS , которое как раз указывает классу, что он является расширенным(дополненным). За этим ключевым словом идет имя класса, от которого наследуется содержимое класса-родителя. Вся прелесть дочернего (наследующего) класса в том, что в его методах есть возможность напрямую обращаться к свойствам и методам класса-родителя(ей) . Это избавляет программиста от лишних ссылок и указателей.

При том даже допускается использование одинаковых имен свойств и методов для родителя и потомка. Но если писать в таком стиле, придется для доступа к ресурсам класса-родителя(ей) использовать ключевое слово BASE (базовый). Пример:

Type SharedType
    ID As Integer ' идентификатор объекта
    Declare Sub Explosion() ' взрыв объекта
End Type

Sub SharedType.Explosion()
    Print "Main class"
End Sub

' Класс планет
Type Planets Extends SharedType
    ID As Integer ' идентификатор планеты
    Declare Sub Explosion()
End Type


' метод вращения планет
Sub Planets.Explosion()
    Base.Explosion()' вызываем метод родителя
    Print Base.ID ' Узнаем идентификатор объекта
    Print ID ' Узнаем идентификатор планеты
End Sub

Dim Obj As Planets = Type(10)' указываем идентификатор объекта при создании
Obj.ID = 20 ' указываем идентификатор планеты 
Obj.Explosion ' вызываем метод потомка
Sleep


Наследование может быть многоуровневым и при таком раскладе для доступа к разным ступеням родителей можно использовать цепочку из ключевых BASE:

Base.Base.ID


Чем больше ключевых слов BASE, тем ближе к самому верхнему родителю в иерархии.

Благодаря ключевому слову BASE , есть возможность довольно простой инициализации свойств главного родителя (стоящего на самом верху иерархии). Пример из справки:

Type SimpleParent
    As Integer a, b, c
End Type

Type Child extends SimpleParent
    Declare Constructor( )
End Type

Constructor Child( )
    Base( 1, 2, 3 )
End Constructor

Dim Obj As Child
? Obj.a,Obj.b,Obj.c
Sleep


Если вернуться к ключевому слову EXTENDS, то благодаря ему есть возможность создавать классы на базе встроенного "нулевого" класса OBJECT. Это дает свои преимущества:

1) Есть возможность создать класс и в нем указать декларацию метода без дополнительной переменной. То есть в версии ниже 0.24 , создать такой класс было нельзя:

Type MyClass
    Declare Sub Plus()
End Type


Компилятор выдаст ошибку о том что тип пустой и чтобы исправить ошибку, надо указать хоть одну переменную. Но используя наследование от типа OBJECT , можно создать вообще пустой класс:

Type MyClass Extends Object

End Type


Нет необходимости в лишней переменной.

2) Появляется возможность определить тип объекта, используя ключевое слово IS. Пример:

Type MyClass Extends Object

End Type

Type Round Extends MyClass

End Type

Type Box Extends MyClass

End Type

Sub init(Obj As OBJECT Ptr)
    If *Obj Is Round Then 
        Print "ROUND"
    Elseif *Obj Is Box Then
        Print "BOX"
    Else
        Print "PARENT"
    Endif
End Sub

' Создаем главный объект
Dim Obj As MyClass 

' Создаем объект круг
Dim R As Round 

' Создаем объект прямоугольник
Dim B As Box

' Проверяем
init(@Obj)
init(@R)
init(@B)
Sleep


Примечание:

И хоть в версии компилятора 0.24 допускается использование имен сходных с именами базовых классов (пример: Dim MyClass as MyClass) , привыкать к этому лучше не нужно. В версии 0.25 компилятор такой вольности уже не позволит. Для справки, в версии 0.25 заявлены новые возможности ООП: абстрактные и виртуальные методы. Но пока я даже не вижу их применения в реальных программах (просто не хватает опыта). Удачи!