Наследование¶
Ü поддерживает наследование для классов. Наследование позволяет создавать классы, частично заимствующие состав и поведение классов-предков. Наследование также позволяет реализовать динамический полиморфизм.
В наследовании могут принимать участие только полиморфные классы. Полиморфными являются классы, объявленные с использованием ключевых слов polymorph, abstract или inteface, или классы, имеющие предков.
class A polymorph // Класс, от которого можно наследоваться.
{}
class B interface // Интерфейс. От него можно наследоваться, но сам он имеет ряд ограничений на своё содержимое.
{}
class C abstract // Тоже полиморфный класс, но в котором разрешены нереализованные виртуальные функции.
{}
class D : C // Полиморфный класс, т. к. имеет предка.
{}
class E : B // Полиморфный класс с предком-интерфейсом.
{}
class F : A, B // Полиморфный класс с двумя предками, один из которых - интерфейс.
{}
class G final : F // Полиморфный класс, от которого нельзя унаследоваться.
{}
Правила наследования¶
Класс может иметь не более одного неинтерфейсного предка и любое количество интерфейсных предков.
Неинтерфейсный предковый класс считается базой класса. Обратиться к нему можно с использованием ключевого слова base.
base - это this, но преобразованный в тип базового класса.
Существует ряд особых видов полиморфных классов:
- interfaceкласс, это такой полиморфный класс, у которого не может быть базового класса, полей, виртуальных методов с реализацией.
- finalкласс, это такой полиморфный класс, от которого уже нельзя унаследоваться.
- abstractкласс, это такой полиморфный класс, у которого могут быть нереализованные виртуальные методы. У полиморфных классов, не помеченных как- abstractили- interfaceвсе виртуальные методы должны иметь реализацию.
Ограничения абстрактных классов и интерфейсов¶
Абстрактные классы и интерфейсы не являются полноценными классами, они имеют ряд ограничений:
- Нельзя создать экземпляр абстрактного класса или интерфейса, вместо этого можно только унаследоваться от них и создать экземпляр класса-потомка. 
- Интерфейсы не могут иметь конструкторов. Они им не нужны, т. к. у них нету полей, которые необходимо было бы инициализировать в конструкторах. 
- Абстрактные классы могут иметь конструкторы, но в них не доступен - this, что означает, что можно обращаться только к конкретным полям по имени и нельзя вызывать никакие методы.
- Интерфейсы и абстрактные классы могут иметь деструкторы, но в них - thisтакже не доступен.
Преобразование ссылок¶
Ссылка на класс-потомок может быть явно или неявно преобразована в ссылку на класс-предок. Неявные преобразования возможны:
- При инициализации ссылочной переменной или ссылочного поля 
- При передаче аргумента в функцию 
- При возврате значения из функции 
Состав наследуемого содержимого¶
Класс-потомок наследует от класса-предка public и protected члены. private члены класса не наследуются.
Не наследуются конструкторы, деструкторы, операторы присваивания, операторы сравнения (==, <=>).
Методы наследуются, но тип this у них остаётся таким же, как и у предкового класса, за исключением случая, когда происходит переопределение виртуального метода.
Виртуальные методы¶
Виртуальный метод - это такой метод, который вызывается косвенно, и конкретная реализация которого может быть различной. Виртуальный метод объявленный в одном классе, может быть переопределён в классе-потомке.
Объявляется виртуальный метод с использованием ряда ключевых слов:
- virtual- метод впервые объявляется как виртуальный. В этом случае у предкового класса не должно быть такого метода.
- virtual pure- метод впервые объявляется как виртуальный. Реализация данного метода запрещена.
- virtual override- метод переопределяет метод предкового класса.
- virtual final- метод переопределяет метод предкового класса. Дальнейшей переопределение в классах-потомках для этого метода запрещено.
Виртуальные методы должны всегда иметь параметр this.
Он должен быть изменяемой или неизменяемой ссылкой, byval this не допускается.
class A interface
{
    fn virtual pure Foo( this, i32 x );
}
class B polymorph
{
    fn virtual Bar( mut this, f32 y );
}
class C : A, B
{
    fn virtual override Foo( this, i32 x );
    fn virtual final Bar( mut this, f32 y );
}
fn CallFoo( A& a, i32 x )
{
    a.Foo(x);
}
fn CallBar( B &mut b, f32 y )
{
    b.Bar(y);
}
fn Test()
{
    var C mut c;
    CallFoo( c, 42 ); // Будет вызван метод С::Foo
    CallBar( c, 0.25f ); // Будет вызван метод C::Bar
    var B mut b;
    CallBar( b, 3.14f ); // Будет вызван метод B::Bar
}
Деструктор полиморфных классов всегда является виртуальным, его можно таковым и не объявлять.
