Поделиться через


Наследование (F#)

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

Определение отношений наследования

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

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

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

Наследуемые члены

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

Все привязки let и параметры конструкторов являются закрытыми для класса и поэтому они недоступны из производных классов.

Ключевое слово 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. Используемые значения необходимо определять из аргументов, предоставляемых конструктору производного класса.

В следующем примере кода показаны базовый класс и производный класс, при этом производный класс вызывает конструктор базового класса в выражении 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())

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

При создании иерархий объектов можно вместо наследования использовать размеченные объединения. С помощью размеченных объединений можно также моделировать изменение поведения различных объектов, имеющих общий тип. Использование одного размеченного объединения часто позволяет избежать создания нескольких производных классов, которые незначительно отличаются друг от друга. Дополнительные сведения о размеченных объединениях см. в разделе Размеченные объединения (F#).

См. также

Ссылки

Выражения объекта (F#)

Другие ресурсы

Справочник по языку F#

Журнал изменений

Дата

Журнал

Причина

Сентябрь 2010

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

Улучшение информации.