F # - Eredità
Uno dei concetti più importanti nella programmazione orientata agli oggetti è quello dell'ereditarietà. L'ereditarietà ci consente di definire una classe in termini di un'altra classe, il che semplifica la creazione e la manutenzione di un'applicazione. Ciò offre anche l'opportunità di riutilizzare la funzionalità del codice e tempi di implementazione rapidi.
Quando si crea una classe, invece di scrivere membri dati e funzioni membro completamente nuovi, il programmatore può designare che la nuova classe erediti i membri di una classe esistente. Questa classe esistente viene chiamata classe base e la nuova classe viene definita classe derivata.
L'idea di eredità implementa la relazione IS-A. Ad esempio, il mammifero è un animale, il cane è un mammifero quindi anche il cane è un animale e così via.
Classe di base e sottoclasse
Una sottoclasse è derivata da una classe base, che è già definita. Una sottoclasse eredita i membri della classe di base e dispone dei propri membri.
Una sottoclasse viene definita utilizzando il inherit parola chiave come mostrato di seguito -
type MyDerived(...) =
inherit MyBase(...)
In F # una classe può avere al massimo una classe base diretta. Se non si specifica una classe di base utilizzando ilinherit parola chiave, la classe eredita implicitamente da Object.
Nota:
I metodi ei membri della classe base sono disponibili per gli utenti della classe derivata come i membri diretti della classe derivata.
Lascia che i collegamenti ei parametri del costruttore siano privati di una classe e, pertanto, non è possibile accedervi dalle classi derivate.
La parola chiave basesi riferisce all'istanza della classe base. È usato come l'identificatore di sé.
Esempio
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()
Quando compili ed esegui il programma, restituisce il seguente output:
Hi, I'm Mohan
Hi, I'm Zara
Hi, I'm Mariam
Metodi di sostituzione
È possibile sovrascrivere un comportamento predefinito di un metodo della classe base e implementarlo in modo diverso nella sottoclasse o nella classe derivata.
I metodi in F # non possono essere sovrascritti per impostazione predefinita.
Per sovrascrivere i metodi in una classe derivata, devi dichiarare il tuo metodo come sovrascrivibile usando il abstract e default parole chiave come segue:
type Person(name) =
member x.Name = name
abstract Greet : unit -> unit
default x.Greet() = printfn "Hi, I'm %s" x.Name
Ora, il metodo Greet della classe Person può essere sovrascritto nelle classi derivate. Il seguente esempio lo dimostra:
Esempio
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()
Quando compili ed esegui il programma, restituisce il seguente output:
Hi, I'm Mohan
Student Zara
Teacher Mariam.
Classe astratta
A volte è necessario fornire un'implementazione incompleta di un oggetto, che non dovrebbe essere implementata nella realtà. Successivamente, qualche altro programmatore dovrebbe creare sottoclassi della classe astratta per un'implementazione completa.
Ad esempio, la classe Persona non sarà necessaria in un sistema di gestione scolastica. Tuttavia, sarà necessaria la classe Studente o Insegnante. In questi casi, puoi dichiarare la classe Person come classe astratta.
Il AbstractClass attributo dice al compilatore che la classe ha alcuni membri astratti.
Non è possibile creare un'istanza di una classe astratta perché la classe non è completamente implementata.
Il seguente esempio lo dimostra:
Esempio
[<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()
Quando compili ed esegui il programma, restituisce il seguente output:
Student Zara
Teacher Mariam.