Одним из наиболее важных понятий в объектно-ориентированном программировании является наследование. Наследование позволяет нам определять класс в терминах другого класса, что облегчает создание и поддержку приложения. Это также дает возможность повторно использовать функциональность кода и быстрое время реализации.
При создании класса, вместо того, чтобы писать совершенно новые члены-данные и функции-члены, программист может указать, что новый класс должен наследовать члены существующего класса. Этот существующий класс называется базовым классом, а новый класс называется производным классом.
Идея наследования реализует отношения IS-A. Например, млекопитающее — это животное, собака — это млекопитающее, следовательно, собака — это тоже животное, и так далее.
Базовый класс и подкласс
Подкласс является производным от базового класса, который уже определен. Подкласс наследует членов базового класса, а также имеет своих собственных членов.
Подкласс определяется с использованием ключевого слова наследия, как показано ниже —
type MyDerived(...) = inherit MyBase(...)
В F # класс может иметь не более одного прямого базового класса. Если вы не укажете базовый класс с помощью ключевого слова inherit, класс неявно наследуется от Object.
Пожалуйста, обратите внимание —
-
Методы и члены базового класса доступны пользователям производного класса, как и прямые члены производного класса.
-
Пусть привязки и параметры конструктора являются частными для класса и, следовательно, не могут быть доступны из производных классов.
-
Ключевое слово base относится к экземпляру базового класса. Он используется как самоидентификатор.
Методы и члены базового класса доступны пользователям производного класса, как и прямые члены производного класса.
Пусть привязки и параметры конструктора являются частными для класса и, следовательно, не могут быть доступны из производных классов.
Ключевое слово base относится к экземпляру базового класса. Он используется как самоидентификатор.
пример
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 может быть переопределен в производных классах. Следующий пример демонстрирует это —
пример
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 сообщает компилятору, что класс имеет некоторые абстрактные члены.
Вы не можете создать экземпляр абстрактного класса, потому что этот класс не полностью реализован.
Следующий пример демонстрирует это —
пример
[<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()
Когда вы компилируете и запускаете программу, она выдает следующий вывод: