Kotlin do Learning to Android Capítulo 6 Classes e Herança

tipo

As classes são declaradas em Kotlin usando a palavra-chave class:

class Invoice {
}

Uma declaração de classe inclui um nome de classe, um cabeçalho de classe (tipos de parâmetro, construtores etc.) e um corpo de classe (conteúdo entre chaves). Tanto o cabeçalho quanto o corpo da classe são opcionais; se uma classe não tiver corpo de classe, as chaves podem ser omitidas.

class Empty

Construtor

Em Kotlin, uma classe pode ter um construtor primário e vários construtores secundários. O construtor primário faz parte do cabeçalho da classe, colocado após o nome da classe e possui parâmetros de tipo opcionais.

class Person constructor(firstName: String) {
}

Se o construtor primário não tiver nenhuma anotação ou modificador visível, seu construtor de palavra-chave poderá ser omitido.

class Person(firstName: String) {
}

O construtor principal não pode conter instruções de código e o código de inicialização pode ser colocado no bloco de inicialização declarado com a palavra-chave init:

class Customer(name: String) {
    init {
        logger.info("Customer initialized with value ${name}")
    }
}

Nota: Os parâmetros no construtor principal podem ser usados ​​no bloco de inicialização e também podem ser usados ​​na inicialização de propriedades no corpo da classe.

class Customer(name: String) {
    val customerKey = name.toUpperCase()
}

Geralmente podemos declarar e inicializar propriedades no construtor principal:

class Person(val firstName: String, val lastName: String, var age: Int) {
    // ...
}

Se o construtor tiver anotações ou modificadores visíveis, a palavra-chave constructor não pode ser omitida e os modificadores devem ser colocados antes do construtor.

class Customer public @Inject constructor(name: String) { ... }

construtor secundário

As classes também podem usar construtor para declarar construtores secundários.

class Person {
    constructor(parent: Person) {
        parent.children.add(this)
    }
}

Se uma classe tiver um construtor primário, cada construtor secundário deverá delegar ao construtor primário ou delegar a outro construtor secundário. Dentro da mesma classe, delegue para um construtor usando a palavra-chave this.

class Person(val name: String) {
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    }
}

Se uma classe não abstrata não tiver nenhum construtor, o sistema gerará automaticamente um construtor primário sem parâmetros e será público. Se você não quiser que a classe tenha um construtor público, precisará declarar um construtor sem argumentos em vez de usar o padrão do sistema.

class DontCreateMe private constructor () {
}

Nota : Na JVM, se um construtor primário tiver valores padrão para todos os parâmetros, o compilador criará automaticamente um construtor sem argumentos com esses valores. Dessa forma, algumas bibliotecas de terceiros, como JackJson ou JPA, podem ser facilmente instanciadas por meio do construtor sem argumentos.

fun main(args: Array<String>) {
    var customer = Customer()
    println(customer.customerName) // admin
    // var student = Student() 
    // 由于 age 没有初始化,自动没有自动创建无参构造函数,编译器报错
}

class Customer(val customerName: String = "admin")

class Student(val name: String = "HanMeimei" , val age: Int)

Criar uma instância da classe

Normalmente podemos chamar o construtor para criar uma instância de uma classe:

val invoice = Invoice()

val customer = Customer("Joe Smith")

Observação : não há nenhuma palavra-chave nova no Kotlin.

membros da classe

Uma classe geralmente inclui as seguintes partes:
- construtor e bloco de inicialização
- função
- atributo
- classe aninhada e classe interna
- declaração de objeto

herdar

Todas as classes em Kotlin herdam de Any por padrão, e Any é uma superclasse que não possui classe pai por padrão. Any não é java.lang.Object; Nota: Any não tem funções exceto equals(), hashCode() e toString().

Podemos declarar o relacionamento de herança por dois pontos seguidos pela classe pai no cabeçalho da classe:

open class Base(p: Int)

class Derived(p: Int) : Base(p)

Se uma classe tiver um construtor primário, sua classe pai deverá ser inicializada quando for herdada, como no código acima.

Se uma classe não tiver um construtor primário, cada construtor secundário precisa inicializar a classe pai com a palavra-chave super ou delegar a outro construtor que inicializou a classe pai. Além disso, diferentes construtores secundários podem chamar diferentes construtores na classe pai.

class MyView : View {
    constructor(ctx: Context) : super(ctx)

    constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
}

A palavra-chave open é o oposto da palavra-chave final em java: ela permite que outras classes herdem desta classe. Todas as classes em Kotlin são finais por padrão.

função de substituição

Ao contrário do java, as funções de substituição no Kotlin devem ser explicitamente declaradas:

open class Base {
    open fun v() {}
    fun nv() {}
}
class Derived() : Base() {
    override fun v() {}
    // fun nv(){} // 不用关键字 override 声明,编辑器会报错
    // override fun nv(){} // 父类中函数不声明为 open ,编译器也报错
}

Uma função de substituição é aberta por padrão e pode ser substituída por subclasses. Se você não deseja que seja substituída por subclasses, pode usar a modificação final:

open class AnotherDerived() : Base() {
    final override fun v() {}
}

substituir atributo

O método de substituição de propriedades é semelhante ao de substituição de funções.Se houver propriedades com o mesmo nome na subclasse e na classe pai, as propriedades na subclasse devem ser modificadas com substituição e os tipos de propriedade são compatíveis.

open class Foo {
    open val x: Int get { ... }
}

class Bar1 : Foo() {
    override val x: Int = ...
}

Ele pode ser substituído pela inicialização como acima ou usando uma função getter:

open class A{
    open val x:Int = 0
}

class B : A(){
    override val x: Int
        get() = TODO("not implemented")
}

Se for do tipo var e não for inicializado ao substituir, tanto o getter quanto o setter devem ter:

open class A{
    open var x:Int = 0
}

class B : A(){
    override var x: Int
        get() = TODO("not implemented")
        set(value){...}
}

Você também pode substituir uma propriedade do tipo val por uma propriedade do tipo var, mas não o contrário. Porque uma propriedade do tipo val essencialmente declara uma função getter, e substituí-la por var apenas adiciona uma função setter adicional na subclasse. Além disso, você também pode substituir propriedades no construtor principal:

interface Foo {
    val count: Int
}

class Bar1(override val count: Int) : Foo

class Bar2 : Foo {
    override var count: Int = 0
}

Nota : Interfaces e membros de interfaces são abertos por padrão.

substituir regras

Se uma classe e sua classe pai imediata tiverem membros com o mesmo nome, esses membros devem ser substituídos; além disso, em subclasses, podemos usar super para determinar qual membro de qual classe pai (interface pai) é chamado.

open class A {
    open fun f() { print("A") }
    fun a() { print("a") }
}

interface B {
    fun f() { print("B") } 
    fun b() { print("b") }
}

class C() : A(), B {
    override fun f() {
        super<A>.f() // A.f()
        super<B>.f() // B.f()
    }
}

classe abstrata

Uma classe pode ser declarada abstrata com abstract. Os membros de uma classe abstrata não precisam ser implementados em si.Além disso, não precisamos declarar aberto para a classe abstrata e seus membros, que também podem ser herdados.

Também podemos substituir uma função não abstrata de uma classe não abstrata por uma função abstrata de uma classe abstrata:

open class Base {
    open fun f() {}
}

abstract class Derived : Base() {
    override abstract fun f()
}

objeto companheiro

Ao contrário de java ou C#, em Kotlin as classes não possuem métodos estáticos. Na maioria dos casos, as funções de nível de pacote podem ser usadas. Se você precisa declarar uma função que pode ser chamada sem instanciação de classe e pode acessar a estrutura interna desta classe, então você pode declarar um objeto nesta classe. Se você declarar um objeto complementar na classe, poderá chamar a função desse objeto da mesma forma que chama um método estático em Java/C#.

Acho que você gosta

Origin blog.csdn.net/niuzhucedenglu/article/details/72866581
Recomendado
Clasificación