F # - Herança
Um dos conceitos mais importantes na programação orientada a objetos é o de herança. A herança nos permite definir uma classe em termos de outra classe, o que torna mais fácil criar e manter um aplicativo. Isso também oferece uma oportunidade de reutilizar a funcionalidade do código e tempo de implementação rápido.
Ao criar uma classe, em vez de escrever membros de dados e funções de membro completamente novos, o programador pode designar que a nova classe deve herdar os membros de uma classe existente. Essa classe existente é chamada de classe base e a nova classe é chamada de classe derivada.
A ideia de herança implementa o relacionamento IS-A. Por exemplo, o mamífero é um animal, o cão é um mamífero, portanto, o cão é também um animal e assim por diante.
Classe Base e Subclasse
Uma subclasse é derivada de uma classe base, que já está definida. Uma subclasse herda os membros da classe base, bem como tem seus próprios membros.
Uma subclasse é definida usando o inherit palavra-chave conforme mostrado abaixo -
type MyDerived(...) =
inherit MyBase(...)
Em F #, uma classe pode ter no máximo uma classe base direta. Se você não especificar uma classe base usando oinherit palavra-chave, a classe herda implicitamente de Object.
Observe -
Os métodos e membros da classe base estão disponíveis para usuários da classe derivada, como os membros diretos da classe derivada.
Deixe que as ligações e os parâmetros do construtor sejam privados para uma classe e, portanto, não podem ser acessados de classes derivadas.
A palavra-chave baserefere-se à instância da classe base. Ele é usado como o auto-identificador.
Exemplo
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 você compila e executa o programa, ele produz a seguinte saída -
Hi, I'm Mohan
Hi, I'm Zara
Hi, I'm Mariam
Métodos de substituição
Você pode substituir um comportamento padrão de um método da classe base e implementá-lo de maneira diferente na subclasse ou na classe derivada.
Os métodos em F # não podem ser substituídos por padrão.
Para substituir métodos em uma classe derivada, você deve declarar seu método como substituível usando o abstract e default palavras-chave da seguinte forma -
type Person(name) =
member x.Name = name
abstract Greet : unit -> unit
default x.Greet() = printfn "Hi, I'm %s" x.Name
Agora, o método Greet da classe Person pode ser substituído nas classes derivadas. O exemplo a seguir demonstra isso -
Exemplo
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 você compila e executa o programa, ele produz a seguinte saída -
Hi, I'm Mohan
Student Zara
Teacher Mariam.
Classe Abstrata
Às vezes, você precisa fornecer uma implementação incompleta de um objeto, que não deveria ser implementada na realidade. Posteriormente, algum outro programador deve criar subclasses da classe abstrata para uma implementação completa.
Por exemplo, a classe Person não será necessária em um Sistema de Gestão Escolar. No entanto, a classe do aluno ou do professor será necessária. Nesses casos, você pode declarar a classe Person como uma classe abstrata.
o AbstractClass atributo informa ao compilador que a classe possui alguns membros abstratos.
Você não pode criar uma instância de uma classe abstrata porque a classe não está totalmente implementada.
O exemplo a seguir demonstra isso -
Exemplo
[<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 você compila e executa o programa, ele produz a seguinte saída -
Student Zara
Teacher Mariam.