F # - Héritage

L'un des concepts les plus importants de la programmation orientée objet est celui de l'héritage. L'héritage nous permet de définir une classe en termes d'une autre classe, ce qui facilite la création et la maintenance d'une application. Cela offre également la possibilité de réutiliser la fonctionnalité de code et un temps de mise en œuvre rapide.

Lors de la création d'une classe, au lieu d'écrire des membres de données et des fonctions membres complètement nouveaux, le programmeur peut désigner que la nouvelle classe doit hériter des membres d'une classe existante. Cette classe existante est appelée la classe de base et la nouvelle classe est appelée la classe dérivée.

L'idée d'héritage met en œuvre la relation IS-A. Par exemple, le mammifère EST un animal, le chien IS-A, le mammifère donc le chien IS-A également, etc.

Classe de base et sous-classe

Une sous-classe est dérivée d'une classe de base, qui est déjà définie. Une sous-classe hérite des membres de la classe de base, ainsi que de ses propres membres.

Une sous-classe est définie à l'aide du inherit mot-clé comme indiqué ci-dessous -

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

En F #, une classe peut avoir au plus une classe de base directe. Si vous ne spécifiez pas de classe de base en utilisant leinherit mot-clé, la classe hérite implicitement de Object.

Veuillez noter -

  • Les méthodes et les membres de la classe de base sont disponibles pour les utilisateurs de la classe dérivée comme les membres directs de la classe dérivée.

  • Laissez les liaisons et les paramètres du constructeur sont privés pour une classe et, par conséquent, ne sont pas accessibles à partir des classes dérivées.

  • Le mot clé basefait référence à l'instance de classe de base. Il est utilisé comme l'auto-identifiant.

Exemple

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()

Lorsque vous compilez et exécutez le programme, il produit la sortie suivante -

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

Remplacer les méthodes

Vous pouvez remplacer un comportement par défaut d'une méthode de classe de base et l'implémenter différemment dans la sous-classe ou la classe dérivée.

Les méthodes en F # ne sont pas remplaçables par défaut.

Pour remplacer des méthodes dans une classe dérivée, vous devez déclarer votre méthode comme substituable à l'aide du abstract et default mots-clés comme suit -

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

Désormais, la méthode Greet de la classe Person peut être remplacée dans les classes dérivées. L'exemple suivant illustre ceci -

Exemple

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()

Lorsque vous compilez et exécutez le programme, il produit la sortie suivante -

Hi, I'm Mohan
Student Zara
Teacher Mariam.

Classe abstraite

Parfois, vous devez fournir une implémentation incomplète d'un objet, qui ne doit pas être implémentée dans la réalité. Plus tard, un autre programmeur devrait créer des sous-classes de la classe abstraite pour une implémentation complète.

Par exemple, la classe Personne ne sera pas nécessaire dans un système de gestion scolaire. Cependant, la classe Étudiant ou Professeur sera nécessaire. Dans de tels cas, vous pouvez déclarer la classe Person en tant que classe abstraite.

le AbstractClass L'attribut indique au compilateur que la classe a des membres abstraits.

Vous ne pouvez pas créer une instance d'une classe abstraite car la classe n'est pas entièrement implémentée.

L'exemple suivant illustre ceci -

Exemple

[<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()

Lorsque vous compilez et exécutez le programme, il produit la sortie suivante -

Student Zara
Teacher Mariam.