Students Save 30%! Learn & create with unlimited courses & creative assets Students Save 30%! Save Now
Advertisement
  1. Code
  2. Kotlin
Code

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

by
Difficulty:IntermediateLength:LongLanguages:
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应用程序开发帖子!


Envato qr branded
关注我们的公众号
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.