美文网首页
Kotlin 中的接口和抽象类

Kotlin 中的接口和抽象类

作者: 安安_660c | 来源:发表于2022-10-14 15:29 被阅读0次

在面向对象编程(OOP)之前,编码要复杂得多,因为像C这样的语言不允许你在高层次上抽象概念。抽象通过将共同特征组合在一起来创建对象来帮助您构建项目。例如,毛皮颜色,尾巴长度和年龄是制作猫的特征。

从本质上讲,抽象通过提供定义真实世界对象的工具使编码更简单。它还具有其他好处,例如使代码更易于阅读,理解和维护。但是,它也可能使您的生活复杂化。

在本教程中,您将探索抽象类和接口之间的差异,并了解何时使用它们。您将创建动物园指南,这是一个显示不同动物信息的应用程序。在此过程中,您将了解到:
1、关于继承。
2、如何实现抽象类和接口。
3、抽象类和接口之间的差异。
4、创建一个利用抽象类、接口和继承的应用程序。

我们先看一个应用程序,可以看到它有两个屏幕:
主屏幕显示您可以单击的动物列表。
第二个屏幕显示有关您选择的动物的一些详细信息。
项目的结构如下:



该项目包括六种动物:蝙蝠,大象,长颈鹿,狮子,鹦鹉和企鹅。还有两个主要类别:鸟类和哺乳动物。
在 Kotlin 中,默认情况下有一个类及其成员。因此,如果要扩展它们,则必须添加关键字
看看动物,哺乳动物和狮子类,看看继承如何运作的演示:

// 1
open class Animal(
    open val name: String,
    @DrawableRes open val image: Int,
    open val food: Food,
    open val habitat: Habitat
) {
  
  open fun getHungerAmount() : Int {
    return 0
  }
  
  //...
}

// 2
open class Mammal(
    override val name: String,
    @DrawableRes override val image: Int,
    override val food: Food,
    override val habitat: Habitat,
    val furColor: List<Int>
) : Animal(name, image, food, habitat)

// 3
class Lion : Mammal(
    "Lion",
    R.drawable.animal_elephant_sample,
    Food.ZEBRAS,
    Habitat.SAVANNA,
    listOf(Color.parseColor("#CB9C70"))
) {
  
  override fun getHungerAmount() : Int {
    return (0..100).random()
  }
}

这就是继承的原则。它是一个OOP概念,也是在类之间建立关系的基本方法。此方法有三个主要问题:
1、由于动物和哺乳动物是,你可以创建它们的实例,这没有任何意义,因为它们只是抽象的概念,而不是具体的,就像狮子一样。这种不规则性是极其危险的。
2、您需要子类来实现父类中的方法和属性。在这种情况下,可以使用构造函数强制子类实现父类中的属性,但不能对方法执行相同的操作。
3、有些哺乳动物具有某些特征,但其他哺乳动物则没有,类不能支持此类行为。

抽象类

您可以将抽象类视为接口和常规类的混合体。抽象类可以具有接口具有的所有内容以及属性和构造函数。因此,可以在抽象类中正确保存状态,但不能实例化抽象类。

抽象类为所有子类提供通用行为。使用抽象类可以创建许多类共有的一组特征。

抽象类可以同时具有常规方法或属性,也可以具有抽象方法或属性。常规方法和属性可以相应地具体主体和值。

相比之下,被定义为抽象的东西还没有一个定义的值。就方法而言,这意味着它没有主体。

每当类使用抽象成员扩展抽象类时,该类必须实现所有抽象成员。当子类必须实现一个方法来创建特定行为时,这是必不可少的。

看看这个例子:

// 1
abstract class Wrestler {
    abstract fun themeMusic(): String
}

// 2
class JohnCena : Wrestler() {
    override fun themeMusic() = "johncena_theme.mp3"
}

与接口不同,抽象类可以有一个构造函数,从而有一个块。这两种方法对于在创建对象时初始化某些内容都是必不可少的。
实现动物抽象类
从模型/动物包中打开动物。使类抽象:

 abstract class Animal

删除现有方法,并将属性作为抽象属性从构造函数移动到类的主体中。

abstract fun getHungerAmount() : Int

  abstract val name: String

  @get:DrawableRes
  abstract val image: Int

  abstract val food: Food

  abstract val habitat: Habitat

对哺乳动物执行相同的操作,这次添加为不可变的抽象属性:

abstract class Mammal : Animal() {

  abstract val furColor: List<Int>
}
对于 Bird,请改为添加一个抽象属性:feathersColor

abstract class Bird: Animal() {

  abstract val feathersColor: List<Int>
}
对于 Bat,这是更新后代码的外观:

class Bat : Mammal() {

  override val furColor: List<Int>
    get() = listOf(
        Color.parseColor("#463D4A")
    )

  override fun getHungerAmount() : Int {
    return (0..100).random()
  }

  override val name: String
    get() = "Bat"

  override val image: Int
    get() = R.drawable.bat

  override val food: Food
    get() = Food.INSECTS

  override val habitat: Habitat
    get() = Habitat.CAVE
}

接口

与抽象类不同,接口定义特定行为而不是模板。从现在开始,我经常将接口称为一种行为,因为接口可以连接原本没有任何共同点的对象。
接口的特性
每次你的类实现一个接口时,它都在签署一个契约。该合约说,一旦类实现了接口,它还必须实现接口内定义的所有成员。但是,您将在下一节中探讨一个例外情况。

由于 Kotlin 不支持多重继承,因此编译器不会让一个子类具有多个父类。它只能扩展一个类。但有一个好消息:您可以根据需要实现任意数量的接口。

接口只能定义开放成员。因此,实现接口的每个类都可以访问每个非私有成员。请记住,抽象方法不能是私有的。

接口应用示例
想象一下,你有两个类,它们只有一个共同点:它们都需要电才能工作。你会做些什么来连接它们?请查看下面的代码,了解如何执行此操作的示例:

// 1
interface Pluggable {
  
    val neededWattToWork: Int
  
    //Measured in Watt
    fun electricityConsumed(wattLimit: Int) : Int

    fun turnOff()
    
    fun turnOn()
}

// 2
class Microwave : Pluggable {
    
    override val neededWattToWork = 15

    override fun electricityConsumed(wattLimit: Int): Int {
        return if (neededWattToWork > wattLimit) {
            turnOff()
            0
        } else {
            turnOn()
            neededWattToWork
        }
    }

    override fun turnOff() {
        println("Turning off..")
    }

    override fun turnOn() {
        println("Turning on..")
    }
}

// 3
class WashingMachine : Pluggable {

    override val neededWattToWork = 60

    override fun electricityConsumed(wattLimit: Int): Int {
        return if (neededWattToWork > wattLimit) {
            turnOff()
            0
        } else {
            turnOn()
            neededWattToWork
        }
    }

    override fun turnOff() {
        println("Turning off..")
    }

    override fun turnOn() {
        println("Turning on..")
    }
}

解决此问题的最佳方法是实现定义常见行为的接口,这正是它的作用。现在,扩展此接口的每个类都需要实现所有成员。这样,它们就可以连接到电源。

在 Java 中,只能在接口内定义常量属性。因此,每次尝试在 Kotlin 中添加属性时,如下所示:

String password = "Password1234";

编译器在引擎盖下添加。在Java中,你必须初始化属性,这样你才能做这样的事情:

String password; //This code won't run

另一方面,Kotlin 允许您在接口内定义只能是非静态属性。当您只处理一个值并且方法太多时,这将变得很有用。定义一个方法只是为了返回一个值是不方便的,即使正如反编译的Java代码所显示的那样,编译器无论如何都会为该属性创建一个方法。


public interface Pluggable {
   int getNeededWattToWork();

   int electricityConsumed(int var1);

   void turnOff();

   void turnOn();
}

但是,Kotlin 不允许您创建属性,因为属性包含三个组件,这里的问题是接口不能存储值,因为它不能有属性。

相关文章

  • About Kotlin-Kotlin中的类2

    About Kotlin(2) 继续昨天的部分。介绍Kotlin中的类。 Kotlin中的类 抽象类和接口 抽象类...

  • 抽象类和接口

    接口:代表的是事物的能力抽象类:反映的是事物的本质 kotlin中的接口 kotlin中的抽象类 kotlin中实...

  • Kotlin---接口与继承

    接口与抽象类的区别 同样在Kotlin中也有接口的概念,与Java不同的是,Kotlin中的接口可以定义变量,但是...

  • kotlin中的面相对象

    目录 抽象类与接口 多态和接口代理 kotlin中接口函数冲突问题 类及其成员的可见性 object(单例模式) ...

  • Kotlin中的面向对象详解

    目录 抽象类与接口 多态和接口代理 kotlin中接口函数冲突问题 类及其成员的可见性 object(单例模式) ...

  • 1.抽象类与接口

    抽象类(abstract) 接口(interface) kotlin中接口可以继承接口 java8之前接口方法是不...

  • Kotlin学习之抽象类和接口

    Kotlin学习之抽象类和接口 抽象类和接口是面向对象的高级特性。 一、抽象类 类和其中的某些成员可以声明为abs...

  • kotlin语言学习08 ——kotlin接口类、抽象类、伴生对

    本小节主要介绍kotlin接口类、抽象类、伴生对象的相关知识。 1、kotlin的接口 在Java中,从jdk8开...

  • Kotlin学历之抽象类与接口

    简述 Kotlin 中的抽象类和接口与 Java 8 类似,同样用到abstract、interface关键字,与...

  • Kotlin 类2 - 抽象类与接口

    Kotlin 类2 - 抽象类与接口 1. Kotlin 类、抽象类、接口的规则: 「单继承多现实」即一个类只可以...

网友评论

      本文标题:Kotlin 中的接口和抽象类

      本文链接:https://www.haomeiwen.com/subject/hkkczrtx.html