Herança de Kotlin (com exemplos)

Neste artigo, você aprenderá sobre herança. Mais especificamente, o que é herança e como implementá-la em Kotlin (com a ajuda de exemplos).

Herança é um dos principais recursos da programação orientada a objetos. Ele permite ao usuário criar uma nova classe (classe derivada) a partir de uma classe existente (classe base).

A classe derivada herda todos os recursos da classe base e pode ter recursos adicionais próprios.

Antes de entrar em detalhes sobre a herança do Kotlin, recomendamos que você verifique estes dois artigos:

  • Classe e objetos Kotlin
  • Construtor primário Kotlin

Por que herança?

Suponha que, em seu aplicativo, você queira três personagens - um professor de matemática , um jogador de futebol e um empresário .

Visto que todos os personagens são pessoas, eles podem andar e falar. No entanto, eles também têm algumas habilidades especiais. Um professor de matemática pode ensinar matemática , um jogador de futebol pode jogar futebol e um empresário pode dirigir um negócio .

Você pode criar individualmente três classes que podem andar, falar e realizar suas habilidades especiais.

Em cada uma das aulas, você estaria copiando o mesmo código para andar e falar para cada personagem.

Se você quiser adicionar um novo recurso - comer, você precisa implementar o mesmo código para cada personagem. Isso pode facilmente tornar-se sujeito a erros (ao copiar) e códigos duplicados.

Seria muito mais fácil se tivéssemos uma Personaula com recursos básicos como falar, andar, comer, dormir e adicionar habilidades especiais a esses recursos de acordo com nossos personagens. Isso é feito por meio de herança.

Usando herança, agora você não implementar o mesmo código para walk(), talk()e eat()para cada classe. Você só precisa herdá- los.

Portanto, para MathTeacher(classe derivada), você herda todos os recursos de uma Person(classe base) e adiciona um novo recurso teachMath(). Da mesma forma, para a Footballerclasse, você herda todos os recursos da Personclasse e adiciona um novo recurso playFootball()e assim por diante.

Isso torna seu código mais limpo, compreensível e extensível.

É importante lembrar: Ao trabalhar com herança, cada classe derivada deve satisfazer a condição de " ser " uma classe base ou não. No exemplo acima, MathTeacher é a Person , Footballer é a Person . Você não pode ter algo como, Businessman é a Business .

Herança de Kotlin

Vamos tentar implementar a discussão acima no código:

 classe aberta Person (idade: Int) (// código para comer, falar, caminhar) class MathTeacher (age: Int): Person (age) (// outras características do professor de matemática) class Footballer (age: Int): Person ( idade) (// outras características do jogador de futebol) classe Empresário (idade: Int): Pessoa (idade) (// outras características do empresário)

Aqui, Personé uma classe base, e as classes MathTeacher, Footballere Businessmansão derivadas da classe Person.

Observe, a palavra-chave openantes da classe base Person,. É importante.

Por padrão, as aulas em Kotlin são finais. Se você está familiarizado com Java, sabe que uma classe final não pode ser subclassificada. Ao usar a anotação aberta em uma classe, o compilador permite derivar novas classes dela.

Exemplo: Herança Kotlin

 open class Person(age: Int, name: String) ( init ( println("My name is $name.") println("My age is $age") ) ) class MathTeacher(age: Int, name: String): Person(age, name) ( fun teachMaths() ( println("I teach in primary school.") ) ) class Footballer(age: Int, name: String): Person(age, name) ( fun playFootball() ( println("I play for LA Galaxy.") ) ) fun main(args: Array) ( val t1 = MathTeacher(25, "Jack") t1.teachMaths() println() val f1 = Footballer(29, "Christiano") f1.playFootball() )

Quando você executa o programa, a saída será:

Meu nome é Jack. Minha idade é 25 anos, leciono na escola primária. Meu nome é Cristiano. Tenho 29 anos e jogo no LA Galaxy.

Aqui, duas classes MathTeachere Footballersão derivadas da Personclasse.

O construtor primário da Personclasse declarou duas propriedades: idade e nome, e tem um bloco inicializador. O bloco initilizer (e funções de membro) da classe base Personpode ser acessado pelos objetos de classes derivadas ( MathTeachere Footballer).

Classes derivadas MathTeachere Footballertêm suas próprias funções-membro teachMaths()e, playFootball()respectivamente. Essas funções são acessíveis apenas a partir dos objetos de suas respectivas classes.

Quando o objeto t1 da MathTeacherclasse é criado,

 val t1 = MathTeacher (25, "Jack")

Os parâmetros são passados ​​para o construtor primário. No Kotlin, o initbloco é chamado quando o objeto é criado. Como MathTeacheré derivado da Personclasse, ele procura o bloco inicializador na classe base (Pessoa) e o executa. Se o MathTeacherbloco de inicialização tivesse, o compilador também teria executado o bloco de inicialização da classe derivada.

Em seguida, a teachMaths()função para o objeto t1é chamada usando a t1.teachMaths()instrução.

O programa funciona de forma semelhante quando o objeto f1da Footballerclasse é criado. Ele executa o bloco de inicialização da classe base. Então, o playFootball()método da Footballerclasse é chamado usando a instrução f1.playFootball().

Observações importantes: herança de Kotlin

  • Se a classe tiver um construtor primário, a base deve ser inicializada usando os parâmetros do construtor primário. No programa acima, ambas as classes derivadas têm dois parâmetros agee name, e esses dois parâmetros são inicializados no construtor primário na classe base.
    Aqui está outro exemplo:
     open class Person(age: Int, name: String) ( // some code ) class Footballer(age: Int, name: String, club: String): Person(age, name) ( init ( println("Football player $name of age $age and plays for $club.") ) fun playFootball() ( println("I am playing football.") ) ) fun main(args: Array) ( val f1 = Footballer(29, "Cristiano", "LA Galaxy") )  
    Aqui, o construtor primário da classe derivada tem 3 parâmetros e a classe base tem 2 parâmetros. Observe que ambos os parâmetros da classe base são inicializados.
  • No caso de nenhum construtor primário, cada classe base tem que inicializar a base (usando a palavra-chave super), ou delegar a outro construtor que faça isso. Por exemplo,
     fun main(args: Array) ( val p1 = AuthLog("Bad Password") ) open class Log ( var data: String = "" var numberOfData = 0 constructor(_data: String) ( ) constructor(_data: String, _numberOfData: Int) ( data = _data numberOfData = _numberOfData println("$data: $numberOfData times") ) ) class AuthLog: Log ( constructor(_data: String): this("From AuthLog -> + $_data", 10) ( ) constructor(_data: String, _numberOfData: Int): super(_data, _numberOfData) ( ) )
    Para saber mais sobre como esse programa funciona, visite Kotlin Secondary Constructor.

Substituindo Funções e Propriedades de Membro

If the base class and the derived class contains a member function (or property) with the same name, you can need to override the member function of the derived class using override keyword, and use open keyword for the member function of the base class.

Example: Overriding Member Function

 // Empty primary constructor open class Person() ( open fun displayAge(age: Int) ( println("My age is $age.") ) ) class Girl: Person() ( override fun displayAge(age: Int) ( println("My fake age is $(age - 5).") ) ) fun main(args: Array) ( val girl = Girl() girl.displayAge(31) )

When you run the program, the output will be:

 My fake age is 26.

Here, girl.displayAge(31) calls the displayAge() method of the derived class Girl.

You can override property of the base class in similar way.

Visit how Kotlin getters and setters work in Kotlin before you check the example below.

 // Empty primary constructor open class Person() ( open var age: Int = 0 get() = field set(value) ( field = value ) ) class Girl: Person() ( override var age: Int = 0 get() = field set(value) ( field = value - 5 ) ) fun main(args: Array) ( val girl = Girl() girl.age = 31 println("My fake age is $(girl.age).") )

When you run the program, the output will be:

 My fake age is 26.

As you can see, we have used override and open keywords for age property in derived class and base class respectively.

Calling Members of Base Class from Derived Class

Você pode chamar funções (e acessar propriedades) da classe base de uma classe derivada usando a superpalavra-chave. Veja como:

 open class Person() ( open fun displayAge(age: Int) ( println("My actual age is $age.") ) ) class Girl: Person() ( override fun displayAge(age: Int) ( // calling function of base class super.displayAge(age) println("My fake age is $(age - 5).") ) ) fun main(args: Array) ( val girl = Girl() girl.displayAge(31) )

Quando você executa o programa, a saída será:

 Minha idade é 31 anos. Minha falsa idade é 26.

Artigos interessantes...