Наследование

Наследование используется для моделирования отношения "is-a" или подчинения в объектно-ориентированном программировании.

Указание связей наследования

Отношения наследования указываются с помощью inherit ключевое слово в объявлении класса. Базовая синтаксическая форма показана в следующем примере.

type MyDerived(...) =
    inherit MyBase(...)

Класс может иметь по крайней мере один прямой базовый класс. Если базовый класс не указан с помощью inherit ключевое слово, класс неявно наследуется от System.Object.

Унаследованные элементы

Если класс наследует от другого класса, методы и члены базового класса доступны пользователям производного класса, как если бы они были прямыми членами производного класса.

Любые параметры привязки и конструктора являются частными для класса и, следовательно, не могут быть доступны из производных классов.

Ключевое слово base доступен в производных классах и ссылается на экземпляр базового класса. Он используется так же, как и самоизнание.

Виртуальные методы и переопределения

Виртуальные методы (и свойства) работают несколько иначе в F# по сравнению с другими языками .NET. Чтобы объявить новый виртуальный элемент, используйте abstract ключевое слово. Это можно сделать независимо от того, предоставляется ли реализация по умолчанию для этого метода. Таким образом, полное определение виртуального метода в базовом классе следует следующему шаблону:

abstract member [method-name] : [type]

default [self-identifier].[method-name] [argument-list] = [method-body]

А в производном классе переопределение этого виртуального метода следует следующему шаблону:

override [self-identifier].[method-name] [argument-list] = [method-body]

Если не указана реализация по умолчанию в базовом классе, базовый класс становится абстрактным.

В следующем примере кода показано объявление нового виртуального метода function1 в базовом классе и переопределение его в производном классе.

type MyClassBase1() =
    let mutable z = 0
    abstract member function1: int -> int

    default u.function1(a: int) =
        z <- z + a
        z

type MyClassDerived1() =
    inherit MyClassBase1()
    override u.function1(a: int) = a + 1

Конструкторы и наследование

Конструктор базового класса должен вызываться в производном классе. Аргументы конструктора базового класса отображаются в списке аргументов в предложении inherit . Значения, используемые, должны быть определены из аргументов, предоставленных конструктору производного класса.

В следующем коде показан базовый класс и производный класс, где производный класс вызывает конструктор базового класса в предложении наследование:

type MyClassBase2(x: int) =
    let mutable z = x * x

    do
        for i in 1..z do
            printf "%d " i


type MyClassDerived2(y: int) =
    inherit MyClassBase2(y * 2)

    do
        for i in 1..y do
            printf "%d " i

В случае нескольких конструкторов можно использовать следующий код. Первая строка конструкторов производных классов — это inherit предложение, а поля отображаются как явные поля, объявленные с val помощью ключевое слово. Дополнительные сведения см. в разделе "Явные поля": ключевое val слово.

type BaseClass =
    val string1 : string
    new (str) = { string1 = str }
    new () = { string1 = "" }

type DerivedClass =
    inherit BaseClass

    val string2 : string
    new (str1, str2) = { inherit BaseClass(str1); string2 = str2 }
    new (str2) = { inherit BaseClass(); string2 = str2 }

let obj1 = DerivedClass("A", "B")
let obj2 = DerivedClass("A")

Альтернативные варианты наследования

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

open System

let object1 =
    { new Object() with
        override this.ToString() = "This overrides object.ToString()" }

printfn "%s" (object1.ToString())

Дополнительные сведения об выражениях объектов см. в разделе "Выражения объектов".

При создании иерархий объектов рекомендуется использовать дискриминируемый союз вместо наследования. Дискриминированные объединения также могут моделировать разнообразное поведение различных объектов, которые имеют общий общий тип. Один различаемый союз часто может устранить необходимость в ряде производных классов, которые являются незначительными вариациями друг друга. Сведения о дискриминированных профсоюзах см. в разделе " Дискриминированные профсоюзы".

См. также