English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Neste artigo, você aprenderá sobre herança. Mais especificamente, o que é herança e como implementar em Kotlin usando herança (com exemplos).
Herança é uma das funcionalidades principais da programação orientada a objetos. Permite que o usuário crie uma nova classe (classe derivada) a partir de uma classe existente (classe base).
As classes derivadas herdaram todas as funcionalidades da classe base e podem ter outras funcionalidades próprias.
Antes de detalhar a herança em Kotlin, recomenda-se que você leia os seguintes dois artigos:
Suponha que suas aplicações precisem de três papéis-umprofessor de matemáticaumatleta de futebole umcomerciante (Businessman).
Como todos os papéis são pessoas, eles podem andar e falar. Mas, eles também têm habilidades especiais. O professor de matemática podetreinador de futebol (teachMath)e ojogar futebol(playFootball), o comerciante podeAdministrar negócios (runBusiness).
Você pode criar três classes separadas que podem andar, falar e executar suas habilidades especiais.
Em cada classe, você replicará o mesmo código de caminhada e fala para cada papel.
Se precisar adicionar novas funcionalidades - Para comer (eat), você precisaria implementar o mesmo código para cada papel. Isso facilmente pode levar a erros (ao copiar) e código repetido.
Se tivermos uma classe Person com funcionalidades básicas, por exemplo, andar, comer, dormir e adicionar habilidades especiais para esses funcionalidades com base em nosso papel, isso tornaria tudo mais fácil. Isso é feito através da herança.
Usando herança, você não precisa implementar o mesmo código walk(), talk() e eat() para cada classe. Você só precisaHerançaElas são suficientes.
Portanto, para MathTeacher (classe derivada), você pode herdar todas as funcionalidades da classe Person (classe base) e adicionar uma nova função teachingMath(). Da mesma forma, para a classe Footballer, você herda todas as funcionalidades da classe Person e adiciona a nova função playFootball(), e assim por diante.
Isso torna seu código mais conciso, compreensível e extensível.
É importante lembrar:Ao lidar com herança, cada classe derivada deve atender aos critérios de ser uma 'classe base'. No exemplo acima, MathTeacher é uma Pessoa (pessoa), Footballer é uma Pessoa (pessoa). Você não pode considerar 'comerciante (Businessman) como empresa (Business)'.
Vamos tentar implementar no código o que discutimos acima:
open class Person(age: Int) { //Código para comer, falar e andar } class MathTeacher(age: Int): Person(age) { //Outras características do professor de matemática } class Footballer(age: Int): Person(age) { //Outras características do jogador de futebol } class Businessman(age: Int): Person(age) { // Outras características do comerciante }
Aqui, Person é a classe base, enquanto as classes MathTeacher, Footballer e Businessman são derivadas da classe Person.
Atenção, a palavra-chave open antes da classe base Person é muito importante.
Por padrão, as classes no Kotlin são finais. Se você estiver familiarizado com Java, saberá que as classes finais não podem ser derivadas. Ao usar a anotação em uma classe, o compilador permite que você derive novas classes dela.
open class Person(age: Int, name: String) { init { println("Meu nome é $name.") println("Minha idade é $age") } } class MathTeacher(age: Int, name: String): Person(age, name) { fun teachMaths() { println("Eu ensino na escola primária.") } } class Footballer(age: Int, name: String): Person(age, name) { fun playFootball() { println("Eu joguei pelo Los Angeles Galaxy.") } } fun main(args: Array<String>) { val t1 = MathTeacher(25, "Jack") t1.teachMaths() println() val f1 = Footballer(29, "Christiano") f1.playFootball() }
A saída do programa ao executar é:
Meu nome é Jack. Minha idade é 25 Eu ensino na escola primária. Meu nome é Cristiano. Minha idade é 29 Eu joguei pelo Los Angeles Galaxy.
Aqui, duas classes MathTeacher e Footballer são derivadas da classe Person.
O construtor principal da classe Person declara duas propriedades: age e name, e possui um bloco de inicialização. Os objetos das classes derivadas de Person (MathTeacher e Footballer) podem acessar o bloco de inicialização (e os métodos) da classe base.
As classes MathTeacher e Footballer têm seus próprios métodos membros teachMaths() e playFootball(). Esses métodos podem ser acessados apenas pelos objetos de suas próprias classes.
ao criar um objeto da classe MathTeacher t1 ao invés de
val t1 = MathTeacher(25, "Jack")
os parâmetros serão passados para o construtor principal. No Kotlin, ao criar um objeto, é chamado o bloco init. Como o MathTeacher é derivado da classe Person, ele encontrará e executará o bloco de inicialização na classe base (Person). Se o MathTeacher tiver um bloco init, o compilador também executará o bloco de inicialização da classe derivada.
Em seguida, usando t1.teachMaths() chama a função teachMaths() do objeto t1função teachMaths().
criar um objeto da classe f1 ao invés de1.playFootball() chama o método playFootball() da classe Footballer.
Se a classe tiver um construtor primário, deve usar os parâmetros do construtor primário para inicializar a classe base. No programa acima, os dois subclasses têm dois parâmetros age e name, e esses parâmetros estão inicializados no construtor principal da classe base.
Este é outro exemplo:
open class Person(age: Int, name: String) { // algum código } class Footballer(age: Int, name: String, club: String): Person(age, name) { init { println("O jogador de futebol de $age anos, $name, joga pelo $club.") } fun playFootball() { println("Estou jogando futebol.") } } fun main(args: Array<String>) { val f1 = Footballer(29, "Cristiano", "LA Galaxy") }
Aqui, o construtor principal da classe derivada possui3parâmetros, enquanto a classe base possui2parâmetros. Observe que os dois parâmetros da classe base já foram inicializados.
Se não houver construtor primário, cada classe base deve inicializar a classe base (usando a palavra-chave super) ou delegar a outro construtor que execute essa operação. Por exemplo
fun main(args: Array<String>) { 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 vezes") } } class AuthLog: Log { constructor(_data: String): this("From AuthLog -> + $_data", 10) { } constructor(_data: String, _numberOfData: Int): super(_data, _numberOfData) { } }
Para obter mais informações sobre como o programa funciona, acesseConstrutor secundário do Kotlin.
Se a classe base e a classe derivada contiverem membros com o mesmo nome (ou propriedades), pode ser necessário usar a palavra-chave override para sobrescrever a função do membro da classe derivada e usar a palavra-chave open para a função do membro da classe base.
// Construtor principal vazio open class Person() { open fun displayAge(age: Int) { println("Minha idade é $age.") } } class Girl: Person() { override fun displayAge(age: Int) {}} println("Minha idade virtual é ${age - 5}. } } fun main(args: Array<String>) { val girl = Girl() girl.displayAge(31) }
A saída do programa ao executar é:
sua idade virtual é 26.
Aqui, girl.displayAge(31) Chame o método displayAge() da classe derivada Girl.
Você pode sobrescrever atributos da classe base de uma forma semelhante.
Antes de aprender os seguintes exemplos, você pode acessar Getter e Setter no Kotlin Veja como funciona.
//Construtor principal vazio 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<String>) { val girl = Girl() girl.age = 31 println("Minha idade virtual é ${girl.age}.") }
A saída do programa ao executar é:
Minha idade virtual é 26.
Como você vê, usamos as palavras-chave override e open para a propriedade age tanto na classe derivada quanto na classe base.
Você pode usar a palavra-chave super para chamar funções da classe base a partir da classe derivada (e acessar atributos). Veja como fazer:
open class Person() { open fun displayAge(age: Int) { println("Minha idade real é $age.") } } class Girl: Person() { override fun displayAge(age: Int) {}} //Chamada de função da classe base super.displayAge(age) println("Minha idade virtual é ${age - 5}. } } fun main(args: Array<String>) { val girl = Girl() girl.displayAge(31) }
A saída do programa ao executar é:
Minha idade real é 31. Minha idade virtual é 26.