F # - dziedziczenie
Jedną z najważniejszych koncepcji programowania obiektowego jest dziedziczenie. Dziedziczenie pozwala nam zdefiniować klasę pod względem innej klasy, co ułatwia tworzenie i utrzymywanie aplikacji. Daje to również możliwość ponownego wykorzystania funkcjonalności kodu i szybkiego czasu implementacji.
Tworząc klasę, zamiast pisać zupełnie nowe składowe danych i funkcje składowe, programista może wyznaczyć, że nowa klasa powinna dziedziczyć składowe istniejącej klasy. Ta istniejąca klasa jest nazywana klasą bazową, a nowa klasa jest nazywana klasą pochodną.
Idea dziedziczenia implementuje relację IS-A. Na przykład, ssak JEST zwierzęciem, pies IS-A ssak, stąd pies również jest zwierzęciem IS-A i tak dalej.
Klasa podstawowa i podklasa
Podklasa pochodzi z klasy bazowej, która jest już zdefiniowana. Podklasa dziedziczy członków klasy bazowej, a także ma swoich własnych członków.
Podklasa jest definiowana za pomocą inherit słowo kluczowe, jak pokazano poniżej -
type MyDerived(...) =
inherit MyBase(...)
W języku F # klasa może mieć co najwyżej jedną bezpośrednią klasę bazową. Jeśli nie określisz klasy bazowej przy użyciuinherit słowo kluczowe, klasa dziedziczy niejawnie po Object.
Uwaga -
Metody i elementy członkowskie klasy bazowej są dostępne dla użytkowników klasy pochodnej, podobnie jak bezpośredni członkowie klasy pochodnej.
Niech powiązania i parametry konstruktora są prywatne dla klasy i dlatego nie można uzyskać do nich dostępu z klas pochodnych.
Słowo kluczowe baseodwołuje się do instancji klasy bazowej. Jest używany jako własny identyfikator.
Przykład
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()
Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -
Hi, I'm Mohan
Hi, I'm Zara
Hi, I'm Mariam
Metody zastępujące
Można przesłonić domyślne zachowanie metody klasy bazowej i zaimplementować je inaczej w podklasie lub klasie pochodnej.
Metody w języku F # nie są domyślnie zastępowalne.
Aby przesłonić metody w klasie pochodnej, musisz zadeklarować swoją metodę jako możliwą do zastąpienia przy użyciu abstract i default słowa kluczowe w następujący sposób -
type Person(name) =
member x.Name = name
abstract Greet : unit -> unit
default x.Greet() = printfn "Hi, I'm %s" x.Name
Teraz metodę Greet klasy Person można zastąpić w klasach pochodnych. Poniższy przykład demonstruje to -
Przykład
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()
Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -
Hi, I'm Mohan
Student Zara
Teacher Mariam.
Klasa abstrakcyjna
Czasami trzeba zapewnić niepełną implementację obiektu, który w rzeczywistości nie powinien być implementowany. Później jakiś inny programista powinien utworzyć podklasy klasy abstrakcyjnej do pełnej implementacji.
Na przykład klasa Person nie będzie potrzebna w systemie zarządzania szkołą. Jednak klasa ucznia lub nauczyciela będzie potrzebna. W takich przypadkach można zadeklarować klasę Person jako klasę abstrakcyjną.
Plik AbstractClass atrybut mówi kompilatorowi, że klasa ma kilka abstrakcyjnych elementów członkowskich.
Nie można utworzyć wystąpienia klasy abstrakcyjnej, ponieważ klasa ta nie jest w pełni zaimplementowana.
Poniższy przykład demonstruje to -
Przykład
[<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()
Kiedy kompilujesz i wykonujesz program, daje to następujące dane wyjściowe -
Student Zara
Teacher Mariam.