Kotlin de Learning to Android Capítulo 6 Clases y herencia

amable

Las clases se declaran en Kotlin usando la palabra clave class:

class Invoice {
}

Una declaración de clase incluye un nombre de clase, un encabezado de clase (tipos de parámetros, constructores, etc.) y un cuerpo de clase (contenido entre llaves). Tanto el encabezado de la clase como el cuerpo de la clase son opcionales; si una clase no tiene cuerpo de clase, se pueden omitir las llaves.

class Empty

Constructor

En Kotlin, una clase puede tener un constructor principal y varios constructores secundarios. El constructor principal forma parte del encabezado de la clase, se coloca después del nombre de la clase y tiene parámetros de tipo opcionales.

class Person constructor(firstName: String) {
}

Si el constructor principal no tiene anotaciones ni modificadores visibles, se puede omitir su palabra clave constructor.

class Person(firstName: String) {
}

El constructor principal no puede contener declaraciones de código y el código de inicialización se puede colocar en el bloque de inicialización declarado con la palabra clave init:

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

Nota: Los parámetros en el constructor principal se pueden usar en el bloque de inicialización y también se pueden usar en la inicialización de propiedades en el cuerpo de la clase.

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

Generalmente podemos declarar e inicializar propiedades en el constructor principal:

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

Si el constructor tiene anotaciones o modificadores visibles, la palabra clave constructor no se puede omitir y los modificadores deben colocarse antes del constructor.

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

constructor secundario

Las clases también pueden usar constructor para declarar constructores secundarios.

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

Si una clase tiene un constructor primario, cada constructor secundario debe delegar al constructor primario o delegar a otro constructor secundario. Dentro de la misma clase, delega a un constructor usando la palabra clave this.

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

Si una clase no abstracta no tiene ningún constructor, el sistema generará automáticamente un constructor primario sin parámetros y es público. Si no desea que la clase tenga un constructor público, debe declarar un constructor sin argumentos en lugar de usar el valor predeterminado del sistema.

class DontCreateMe private constructor () {
}

Nota : en la JVM, si un constructor principal tiene valores predeterminados para todos los parámetros, el compilador creará automáticamente un constructor sin argumentos con esos valores. De esta forma, algunas bibliotecas de terceros, como JackJson o JPA, se pueden crear instancias fácilmente a través del constructor sin 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)

Crear una instancia de la clase.

Por lo general, podemos llamar al constructor para crear una instancia de una clase:

val invoice = Invoice()

val customer = Customer("Joe Smith")

Nota : no hay ninguna palabra clave nueva en Kotlin.

miembros de la clase

Una clase generalmente incluye las siguientes partes:
- constructor y bloque de inicialización
- función
- atributo
- clase anidada y clase interna
- declaración de objeto

heredar

Todas las clases en Kotlin heredan de Any de forma predeterminada, y Any es una superclase que no tiene una clase principal de forma predeterminada. Any no es java.lang.Object; Nota: Any no tiene ninguna función excepto equals(), hashCode() y toString().

Podemos declarar la relación de herencia por dos puntos seguidos de la clase principal en el encabezado de la clase:

open class Base(p: Int)

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

Si una clase tiene un constructor principal, su clase principal debe inicializarse cuando se hereda, como en el código anterior.

Si una clase no tiene un constructor principal, cada constructor secundario debe inicializar la clase principal con la palabra clave super o delegar a otro constructor que haya inicializado la clase principal. Además, diferentes constructores secundarios pueden llamar a diferentes constructores en la clase principal.

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

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

La palabra clave open es lo opuesto a la palabra clave final en java: permite que otras clases hereden de esta clase. Todas las clases en Kotlin son definitivas de forma predeterminada.

función de anulación

A diferencia de Java, las funciones de anulación en Kotlin deben declararse explícitamente:

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

Una función de anulación está abierta de forma predeterminada y las subclases pueden anularla. Si no desea que las subclases la anulen, puede usar la modificación final:

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

anular atributo

El método de invalidación de propiedades es similar al de invalidación de funciones.Si hay propiedades con el mismo nombre en la subclase que en la clase principal, las propiedades de la subclase deben modificarse con invalidación y los tipos de propiedad son compatibles.

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

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

Se puede anular mediante la inicialización como se indicó anteriormente, o mediante el uso de una función getter:

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

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

Si es de tipo var y no se inicializó al anular, tanto getter como setter deben tener:

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

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

También puede anular una propiedad de tipo val con una propiedad de tipo var, pero no al revés. Porque una propiedad de tipo val esencialmente declara una función getter, y anularla con var solo agrega una función setter adicional en la subclase. Además, también puede anular las propiedades en el constructor principal:

interface Foo {
    val count: Int
}

class Bar1(override val count: Int) : Foo

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

Nota : las interfaces y los miembros de las interfaces están abiertos de forma predeterminada.

anular reglas

Si una clase y su clase principal inmediata tienen miembros con el mismo nombre, entonces estos miembros deben anularse; además, en las subclases podemos usar super para determinar a qué miembro de qué clase principal (interfaz principal) se llama.

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()
    }
}

clase abstracta

Una clase se puede declarar abstracta con abstract. Los miembros de una clase abstracta no necesitan implementarse en sí mismos. Además, no necesitamos declarar abiertos para la clase abstracta y sus miembros, que también se pueden heredar.

También podemos anular una función no abstracta de una clase no abstracta con una función abstracta de una clase abstracta:

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

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

objeto compañero

A diferencia de Java o C#, en Kotlin las clases no tienen métodos estáticos. En la mayoría de los casos, se pueden usar funciones a nivel de paquete en su lugar. Si necesita declarar una función a la que se puede llamar sin instanciación de clase y puede acceder a la estructura interna de esta clase, entonces puede declarar un objeto en esta clase. Si declara un objeto complementario en la clase, puede llamar a la función de este objeto como si llamara a un método estático en Java/C#.

Supongo que te gusta

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