7 days of WordPress plugins, themes & templates - for free!* Unlimited asset downloads! Start 7-Day Free Trial
Advertisement
  1. Code
  2. Kotlin

Kotlin From Scratch:抽象类,接口,继承和类型别名

Scroll to top
Read Time: 3 mins
This post is part of a series called Kotlin From Scratch.
Kotlin From Scratch: Advanced Properties and Classes
Kotlin From Scratch: Exception Handling

Chinese (Simplified) (中文(简体)) translation by Zhang Xiang Liang (you can also view the original English article)

Kotlin  是一种编译为Java字节码的现代编程语言。它是免费的,  开源,并有望使Android开发更有趣。

在  前面的文章中,您了解了更多关于Kotlin属性的内容,例如后期初始化,扩展和内联属性。不仅如此,您还了解了Kotlin中的高级类,如数据,枚举,嵌套和密封类。 

在这篇文章中,您将继续通过学习抽象类,接口和继承来了解Kotlin中的面向对象编程。为了获得奖励,您还将了解类型别名。

1.  抽象类

Kotlin支持抽象类 - 就像Java一样,这些类是你永远不打算创建对象的类。如果没有一些具体的(非抽象的)子类,抽象类是不完整的或无用的,你可以从中实例化对象。抽象类的具体子类实现抽象类中定义的所有方法和属性 - 否则该子类也是抽象类! 我们用abstract 修饰符创建一个抽象类  (类似于Java)。 

我们用abstract 修饰符创建一个抽象类  (类似于Java)。 

请注意,并非所有成员都必须是抽象的。换句话说,我们可以在抽象类中实现方法默认实现。 

这里我们fullName() 在抽象类中  创建了非抽象函数  Employee。具体类(抽象类的子类)可以重写抽象方法的默认实现 - 但只有当方法具有open指定的修饰符时(您将在短时间内了解更多内容)。 

我们也可以在抽象类中存储状态。 

即使抽象类没有定义任何方法,我们也需要在实例化之前创建一个子类,如下例所示。

我们的Programmer课程扩展了Employee抽象类。在Kotlin中,我们使用单个冒号字符(:)而不是Java  extends 关键字来扩展类或实现接口。

然后,我们可以创建一个类型对象  Programmer 并调用它的方法 - 无论是在它自己的类还是超类(基类)中。  

有一件事可能会让你大吃一惊,那就是我们有能力用var (mutable)重写一个  val(不可变的)属性  。

确保你明智地使用这个功能!请注意,我们无法使用val反向重写  var 属性 。 

2.接口

接口只是一个相关方法的集合,它通常使您能够告诉对象要执行的操作,以及默认情况下如何执行此操作。(接口中的默认方法是添加到Java 8的新特性。)换句话说,接口是实现类必须遵守的合约。 

使用interface Kotlin中的关键字定义接口  (类似于Java)。 

在上面的代码中,我们已经声明了一个StudentRepository 接口。这个接口包含两个抽象方法:getById()和getResultsById()。请注意,abstract在接口方法中包含关键字是多余的,因为它们已经是隐式抽象的。  .

没有一个或多个实现者,接口是没有用的 - 所以我们创建一个实现这个接口的类。

 这里我们创建了一个StudentLocalDataSource 实现StudentRepository 接口的类  。

我们使用override修饰符来标记要从接口或超类重新定义的方法和属性 - 这与@OverrideJava中的注释类似。

请注意Kotlin中以下附加的接口规则:

  • 一个类可以实现尽可能多的接口,但它只能扩展一个类(类似于Java)。
  • 该  override修改是在Java中的必修课科特林-不同。 
  • 除了方法外,我们还可以在Kotlin界面中声明属性。
  • Kotlin接口方法可以有一个默认实现(类似于Java 8)。

我们来看一个具有默认实现的接口方法的例子。

在前面的代码中,我们添加了delete()一个默认实现的新方法(尽管我没有为演示目的添加实际的实现代码)。 

如果需要,我们也可以自由重写默认实现

如上所述,Kotlin接口可以具有属性 - 但请注意,它不能保持状态。(但是,记住抽象类可以维护状态。)所以下面的带有属性声明的接口定义将起作用。

但是,如果我们试图通过给属性赋值来向接口添加一些状态,它将无法工作。

然而,Kotlin中的接口属性可以有getter和setter方法(尽管只有后者如果该属性是可变的)。另请注意,接口中的属性不能有后台字段。 

如果需要,我们也可以覆盖接口属性,以便重新定义它。 

让我们来看看我们有一个类实现了多个接口的情况下,使用相同的方法签名。这个类如何决定调用哪个接口方法?

这里我们有两个接口具有相同签名的方法funD()。让我们创建一个实现这两个接口并覆盖该funD()方法的类。 

编译器对调用super.funD()方法感到困惑,因为类实现的两个接口具有相同的方法签名。 

为了解决这个问题,我们用尖括号将我们想要调用方法的接口名称包装起来。(IntelliJ IDEA或Android Studio会在您遇到问题时向您提供有关解决此问题的提示。)

在这里,我们将要调用InterfaceA的  funD()  方法。问题解决了! 

3.继承

通过获取现有类的(超类)成员并可能重新定义其默认实现来创建新类(子类)。这种机制在面向对象编程(OOP)中被称为继承。使Kotlin如此精彩的一件事是,它包含了面向对象和函数式编程范例 - 所有这些都在一种语言中。 Kotlin中所有类的基类都是Any。 

Kotlin中所有类的基类都是Any。 

该Any类型与Object我们在Java中使用的类型相同。

Any类型包含以下成员:  equals(),hashcode()以及toString()方法(类似于Java)。 

我们的类不需要明确地扩展这种类型。如果您没有明确指定新类继承的类,则该类将Any隐式扩展。出于这个原因,您通常不需要包含: Any 在代码中,我们在上面的代码中进行演示。  .

现在让我们考虑在Kotlin中创建类,并考虑继承。 

在上面的代码中,GraduateStudent类扩展了超类Student。但是这段代码不会编译。为什么?因为类和方法final默认在Kotlin中。 换句话说,默认情况下它们不能被扩展 - 不像默认情况下打开类和方法的Java。

软件工程最佳实践建议您final 默认开始制作类和方法  - 即,如果它们不是专门用于在子类中重新定义或重写的。Kotlin团队(JetBrains)在开发这种现代语言时运用了这种编码理念和更多开发最佳实践。

对于我们允许从超类创建子类,我们必须用open修饰符明确地标记超类  。此修饰符也适用于应由子类覆盖的任何超类属性或方法。

我们只需open在class关键字前加上修饰符。我们现在已经指示编译器允许我们的Student类可以被扩展。 

如前所述,Kotlin课程的成员默认也是最终的。

在前面的代码中,我们将该schoolFees函数标记为 - open子类可以覆盖它。

在这里,Student超类的开放函数schoolFeesGraduateStudent类重写- 通过overridefun关键字之前添加修饰符。请注意,如果您重写超类或接口的成员,则覆盖成员也将为open默认值,如下例所示:

尽管我们没有用修饰符openGraduateStudent类中标记方法schoolFees(),但我们仍然可以重写它 - 就像我们在ComputerScienceStudent类中所做的那样。为了防止这种情况发生,我们必须将最重要的成员标记为final

请记住,我们可以通过在Kotlin中使用扩展函数向类添加新功能,即使它是最终的。有关扩展功能的更新,请查看我在Kotlin  post中的高级功能。 另外,如果您需要了解如何在不继承最终类新属性的情况下进行回顾,请参阅高级属性和类 帖子中关于扩展属性的部分  。

如果我们的超类具有这样的主构造函数:

然后任何子类都必须调用超类的主构造函数。 

我们可以GraduateStudent照常创建一个类的对象:

如果子类想从其次级构造函数调用超类构造函数,那么我们使用super关键字(类似于如何在Java中调用超类构造函数)。 

如果你需要复习Kotlin中的类构造函数,请访问我的  类和对象  文章。 

4.奖金:输入别名

我们可以在Kotlin中做的另一件令人敬畏的事情是给一个类型一个别名。 

我们来看一个例子。

在上面的类中,我们可以使用Kotlin中的修饰符为属性别名分配String和Int类型  。该修饰符用于在Kotlin中创建任何类型的别名 - 包括您创建的别名。 Persontypealias

正如你所看到的,我们已经创建了一个别名Name和Age在,类型分别为StringInt类型。 现在我们已更换firstName 和lastName 属性类型,以我们的别名Name-和Int类型Age别名。请注意,我们没有创建任何新的类型 - 我们为这些类型创建了一个别名。 

 当您想要为您的Kotlin代码库中的类型提供更好的含义或语义时,这些可以很方便。所以明智地使用它们! 

结论

在本教程中,您了解了Kotlin中更多关于面向对象编程的知识。我们涵盖以下内容:

  • 抽象类
  • 接口
  • 遗产
  • 类型别名

如果您通过我们的Kotlin From Scratch系列学习了Kotlin,请确保您输入了您看到的代码并在IDE上运行它。真正掌握一门新的编程语言(或任何编程概念)的一个很好的技巧就是要确保你不只是阅读学习资源或指南,而且还要输入实际的代码并运行它!

Kotlin From Scratch  系列的下一个教程中  ,您将介绍Kotlin中的异常处理。再见!

要了解有关Kotlin语言的更多信息,我建议访问  Kotlin文档。或者在Envato Tuts上查看我们的其他一些Android应用程序开发帖子!


关注我们的公众号
Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.