Учебники

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

Одним из наиболее важных понятий в объектно-ориентированном программировании является наследование. Наследование позволяет нам определять класс в терминах другого класса, что облегчает создание и поддержку приложения. Это также дает возможность повторно использовать функциональность кода и быстрое время реализации.

При создании класса, вместо того, чтобы писать совершенно новые члены-данные и функции-члены, программист может указать, что новый класс должен наследовать члены существующего класса. Этот существующий класс называется базовым классом, а новый класс называется производным классом.

Идея наследования реализует отношения IS-A. Например, млекопитающее — это животное, собака — это млекопитающее, следовательно, собака — это тоже животное, и так далее.

Базовый класс и подкласс

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

Подкласс определяется с использованием ключевого слова наследия, как показано ниже —

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

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

Пожалуйста, обратите внимание —

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

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

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

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

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

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

пример

Live Demo

type Person(name) =
   member x.Name = name
   member x.Greet() = printfn "Hi, I'm %s" x.Name

type Student(name, studentID : int) =
   inherit Person(name)
   let mutable _GPA = 0.0
   member x.StudentID = studentID
   member x.GPA
      with get() = _GPA
      and set value = _GPA <- value

type Teacher(name, expertise : string) =
   inherit Person(name)

   let mutable _salary = 0.0
   member x.Salary
      with get() = _salary
      and set value = _salary <- value
   member x.Expertise = expertise

//using the subclasses
let p = new Person("Mohan")
let st = new Student("Zara", 1234)
let tr = new Teacher("Mariam", "Java")

p.Greet()
st.Greet()
tr.Greet()

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

Hi, I'm Mohan
Hi, I'm Zara
Hi, I'm Mariam

Переопределяющие методы

Вы можете переопределить поведение по умолчанию метода базового класса и реализовать его по-разному в подклассе или производном классе.

Методы в F # не могут быть переопределены по умолчанию.

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

type Person(name) =
   member x.Name = name
   abstract Greet : unit -> unit
   default x.Greet() = printfn "Hi, I'm %s" x.Name

Теперь метод Greet класса Person может быть переопределен в производных классах. Следующий пример демонстрирует это —

пример

Live Demo

type Person(name) =
   member x.Name = name
   abstract Greet : unit -> unit
   default x.Greet() = printfn "Hi, I'm %s" x.Name

type Student(name, studentID : int) =
   inherit Person(name)

   let mutable _GPA = 0.0

   member x.StudentID = studentID
   member x.GPA
      with get() = _GPA
      and set value = _GPA <- value
   override x.Greet() = printfn "Student %s" x.Name

type Teacher(name, expertise : string) =
   inherit Person(name)
   let mutable _salary = 0.0
   member x.Salary
      with get() = _salary
      and set value = _salary <- value

   member x.Expertise = expertise
   override x.Greet() = printfn "Teacher %s." x.Name

//using the subclasses
let p = new Person("Mohan")
let st = new Student("Zara", 1234)
let tr = new Teacher("Mariam", "Java")

//default Greet
p.Greet()

//Overriden Greet
st.Greet()
tr.Greet()

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

Hi, I'm Mohan
Student Zara
Teacher Mariam.

Абстрактный класс

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

Например, класс Person не понадобится в Системе управления школой. Тем не менее, потребуется класс ученика или учителя. В таких случаях вы можете объявить класс Person как абстрактный класс.

Атрибут AbstractClass сообщает компилятору, что класс имеет некоторые абстрактные члены.

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

Следующий пример демонстрирует это —

пример

Live Demo

[<AbstractClass>]
type Person(name) =
   member x.Name = name
   abstract Greet : unit -> unit

type Student(name, studentID : int) =
   inherit Person(name)
   let mutable _GPA = 0.0
   member x.StudentID = studentID
   member x.GPA
      with get() = _GPA
      and set value = _GPA <- value
   override x.Greet() = printfn "Student %s" x.Name

type Teacher(name, expertise : string) =
   inherit Person(name)
   let mutable _salary = 0.0
   member x.Salary
      with get() = _salary
      and set value = _salary <- value
   member x.Expertise = expertise
   override x.Greet() = printfn "Teacher %s." x.Name

let st = new Student("Zara", 1234)
let tr = new Teacher("Mariam", "Java")

//Overriden Greet
st.Greet()
tr.Greet()

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