F # - Herencia
Uno de los conceptos más importantes de la programación orientada a objetos es el de herencia. La herencia nos permite definir una clase en términos de otra clase, lo que facilita la creación y el mantenimiento de una aplicación. Esto también brinda la oportunidad de reutilizar la funcionalidad del código y el tiempo de implementación rápido.
Al crear una clase, en lugar de escribir miembros de datos y funciones de miembros completamente nuevos, el programador puede designar que la nueva clase debe heredar los miembros de una clase existente. Esta clase existente se denomina clase base y la nueva clase se denomina clase derivada.
La idea de herencia implementa la relación IS-A. Por ejemplo, el mamífero es un animal, el perro es un mamífero y, por lo tanto, el perro es un animal también y así sucesivamente.
Clase base y subclase
Una subclase se deriva de una clase base, que ya está definida. Una subclase hereda los miembros de la clase base, además de tener sus propios miembros.
Una subclase se define utilizando el inherit palabra clave como se muestra a continuación -
type MyDerived(...) =
inherit MyBase(...)
En F #, una clase puede tener como máximo una clase base directa. Si no especifica una clase base utilizando elinherit palabra clave, la clase hereda implícitamente de Object.
Tenga en cuenta:
Los métodos y miembros de la clase base están disponibles para los usuarios de la clase derivada como los miembros directos de la clase derivada.
Deje que los enlaces y los parámetros del constructor sean privados para una clase y, por lo tanto, no se puede acceder a ellos desde clases derivadas.
La palabra clave basese refiere a la instancia de la clase base. Se utiliza como autoidentificador.
Ejemplo
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()
Cuando compila y ejecuta el programa, produce el siguiente resultado:
Hi, I'm Mohan
Hi, I'm Zara
Hi, I'm Mariam
Métodos primordiales
Puede anular un comportamiento predeterminado de un método de clase base e implementarlo de manera diferente en la subclase o la clase derivada.
Los métodos en F # no se pueden reemplazar de forma predeterminada.
Para anular métodos en una clase derivada, debe declarar su método como anulable usando el abstract y default palabras clave de la siguiente manera:
type Person(name) =
member x.Name = name
abstract Greet : unit -> unit
default x.Greet() = printfn "Hi, I'm %s" x.Name
Ahora, el método Greet de la clase Person se puede reemplazar en clases derivadas. El siguiente ejemplo demuestra esto:
Ejemplo
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()
Cuando compila y ejecuta el programa, produce el siguiente resultado:
Hi, I'm Mohan
Student Zara
Teacher Mariam.
Clase abstracta
En ocasiones, es necesario proporcionar una implementación incompleta de un objeto, que no debería implementarse en la realidad. Más tarde, algún otro programador debería crear subclases de la clase abstracta para una implementación completa.
Por ejemplo, la clase Person no será necesaria en un sistema de gestión escolar. Sin embargo, se necesitará la clase de Estudiante o Maestro. En tales casos, puede declarar la clase Person como una clase abstracta.
los AbstractClass El atributo le dice al compilador que la clase tiene algunos miembros abstractos.
No puede crear una instancia de una clase abstracta porque la clase no está completamente implementada.
El siguiente ejemplo demuestra esto:
Ejemplo
[<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()
Cuando compila y ejecuta el programa, produce el siguiente resultado:
Student Zara
Teacher Mariam.