Kotlin - 快速指南



Kotlin - 概述

Kotlin 是一种新的开源编程语言,类似于 Java、JavaScript 等。它是一种高级强类型静态语言,将函数式和技术部分结合在一个地方。目前,Kotlin 针对 Java 和 JavaScript。它在 JVM 上运行。

Kotlin 受其他编程语言的影响,例如 Java、Scala、Groovy、Gosu 等。Kotlin 的语法可能与 JAVA 不完全相同,但是,在内部,Kotlin 依赖于现有的 Java 类库为程序员提供出色的结果。Kotlin 为全球的开发者提供了互操作性、代码安全性和清晰度。

优点和缺点

以下是使用 Kotlin 进行应用程序开发的一些优点。

简单的语言 - Kotlin 是一种函数式语言,非常易于学习。语法与 Java 非常相似,因此很容易记住。Kotlin 更具表达性,这使得您的代码更易于阅读和理解。

简洁 - Kotlin 基于 JVM,并且是一种函数式语言。因此,它减少了其他编程语言中使用的许多样板代码。

运行时和性能 - 更好的性能和更小的运行时。

互操作性 - Kotlin 已经足够成熟,可以以不太复杂的方式构建互操作应用程序。

全新的 - Kotlin 是一种全新的语言,为开发人员提供了一个新的起点。它不是 Java 的替代品,尽管它是在 JVM 上开发的。它被接受为 Android 开发的第一种官方语言。Kotlin 可以定义为 - Kotlin = JAVA + 附加更新的新功能。

以下是 Kotlin 的一些缺点。

命名空间声明 - Kotlin 允许开发人员在顶层声明函数。但是,当在应用程序的许多地方声明相同的函数时,很难理解正在调用哪个函数。

没有静态声明 - Kotlin 没有像 Java 那样的常用静态处理修饰符,这可能会给传统的 Java 开发人员带来一些问题。

Kotlin - 环境设置

但是,如果您仍然希望在本地系统中离线使用 Kotlin,则需要执行以下步骤来配置您的本地工作区。

步骤 1 - 安装 Java 8。

Kotlin 在 JVM 上运行,因此,对于本地 Kotlin 开发来说,使用 JDK 8 非常必要。请参阅 oracle 的官方网站下载并安装 JDK 8 或更高版本。您可能需要设置 JAVA 的环境变量,以便它能够正常工作。为了验证您在 Windows 操作系统中的安装,请在命令提示符中键入“java –version”,作为输出,它将显示您系统中安装的 java 版本。

步骤 2 - 安装 IDE。

互联网上有许多 IDE 可供使用。您可以使用任何您选择的 IDE。您可以在下表中找到不同 IDE 的下载链接。

始终建议使用最新的软件版本以充分利用其功能。

步骤 3 - 配置 Eclipse。

打开 Eclipse 并转到“Eclipse Market Place”。您将看到以下屏幕。

Eclipse Market Place

在搜索框中搜索 Kotlin,并在您的本地系统中安装它。这可能需要一些时间,具体取决于网络速度。安装成功后,您可能需要重新启动 Eclipse。

步骤 4 - Kotlin 项目。

Eclipse 重新启动并安装 Kotlin 后,您将能够即时创建 Kotlin 项目。转到文件 → 新建 → 其他,然后从列表中选择“Kotlin 项目”。

Kotlin project

项目设置完成后,您可以在“SRC”文件夹下创建一个 Kotlin 文件。左键单击“Src”文件夹并点击“新建”。您将获得 Kotlin 文件的选项,否则您可能需要从“其他”中搜索。创建新文件后,您的项目目录将如下所示。

Hello

您的开发环境已准备就绪。继续并在“Hello.kt”文件中添加以下代码段。

实时演示
fun main(args: Array<String>) {
   println("Hello, World!")
}

将其作为 Kotlin 应用程序运行,并在控制台中查看输出,如下面的屏幕截图所示。为了更好地理解和可用性,我们将使用我们的编码场地工具。

Hello, World!

Kotlin - 架构

Kotlin 是一种编程语言,它拥有自己的架构来分配内存并为最终用户生成高质量的输出。以下是 Kotlin 编译器在针对不同类型的语言(例如 Java 和 JavaScript)时将以不同方式工作的情况。

Kotlin 编译器创建字节码,该字节码可以在 JVM 上运行,这与 Java .class 文件生成的字节码完全相同。当两个字节码文件在 JVM 上运行时,它们可以相互通信,这就是 Kotlin 为 Java 建立互操作功能的方式。

Architecture

当 Kotlin 针对 JavaScript 时,Kotlin 编译器会将.kt文件转换为 ES5.1 并为 JavaScript 生成兼容的代码。Kotlin 编译器能够通过 LLVM 创建平台基础兼容的代码。

Kotlin - 基本类型

在本章中,我们将学习 Kotlin 编程语言中可用的基本数据类型。

数字

Kotlin 中数字的表示与 Java 非常相似,但是,Kotlin 不允许不同数据类型的内部转换。下表列出了不同数字的不同变量长度。

类型 大小
双精度 64
浮点数 32
长整型 64
整型 32
短整型 16
字节型 8

在下面的示例中,我们将看到 Kotlin 如何处理不同的数据类型。请在我们的编码场地中输入以下代码集。

实时演示
fun main(args: Array<String>) {
   val a: Int = 10000
   val d: Double = 100.00
   val f: Float = 100.00f
   val l: Long = 1000000004
   val s: Short = 10
   val b: Byte = 1
   
   println("Your Int Value is "+a);
   println("Your Double  Value is "+d);
   println("Your Float Value is "+f);
   println("Your Long Value is "+l);
   println("Your Short Value is "+s);
   println("Your Byte Value is "+b);
}

当您在编码场地中运行上述代码段时,它将在 Web 控制台中生成以下输出。

Your Int Value is 10000
Your Double  Value is 100.0
Your Float Value is 100.0
Your Long Value is 1000000004
Your Short Value is 10
Your Byte Value is 1

字符

Kotlin 使用char表示字符。字符应在单引号中声明,例如‘c’。请在我们的编码场地中输入以下代码,并查看 Kotlin 如何解释字符变量。字符变量不能像数字变量那样声明。Kotlin 变量可以通过两种方式声明 - 一种使用“var”,另一种使用“val”

实时演示
fun main(args: Array<String>) {
   val letter: Char    // defining a variable 
   letter = 'A'        // Assigning a value to it 
   println("$letter")
}

上述代码段将在浏览器输出窗口中产生以下输出。

A

布尔值

布尔值与其他编程语言一样简单。布尔值只有两个值 - 真或假。在下面的示例中,我们将看到 Kotlin 如何解释布尔值。

实时演示
fun main(args: Array<String>) {
   val letter: Boolean   // defining a variable 
   letter = true         // Assinging a value to it 
   println("Your character value is "+"$letter")
}

上述代码段将在浏览器中产生以下输出。

Your character value is true

字符串

字符串是字符数组。与 Java 一样,它们本质上是不可变的。Kotlin 中有两种字符串 - 一种称为原始字符串,另一种称为转义字符串。在下面的示例中,我们将使用这些字符串。

实时演示
fun main(args: Array<String>) {
   var rawString :String  = "I am Raw String!"
   val escapedString : String  = "I am escaped String!\n"
   
   println("Hello!"+escapedString)
   println("Hey!!"+rawString)   
}

转义字符串的上述示例允许在第一个 print 语句后提供额外的行间距。以下是浏览器中的输出。

Hello!I am escaped String!

Hey!!I am Raw String!

数组

数组是同类数据的集合。与 Java 一样,Kotlin 支持不同数据类型的数组。在下面的示例中,我们将使用不同的数组。

实时演示
fun main(args: Array<String>) {
   val numbers: IntArray = intArrayOf(1, 2, 3, 4, 5)
   println("Hey!! I am array Example"+numbers[2])
}

上述代码段产生以下输出。数组的索引与其他编程语言类似。在这里,我们正在搜索第二个索引,其值为“3”。

Hey!! I am array Example3

集合

集合是数据结构中非常重要的一部分,它使软件开发对工程师来说变得容易。Kotlin 有两种类型的集合 - 一种是不可变集合(这意味着无法编辑的列表、映射和集合),另一种是可变集合(这种类型的集合是可编辑的)。务必牢记应用程序中使用的集合类型,因为 Kotlin 系统不会在其中表示任何特定差异。

实时演示
fun main(args: Array<String>) { 
   val numbers: MutableList<Int> = mutableListOf(1, 2, 3) //mutable List 
   val readOnlyView: List<Int> = numbers                  // immutable list 
   println("my mutable list--"+numbers)        // prints "[1, 2, 3]" 
   numbers.add(4) 
   println("my mutable list after addition --"+numbers)        // prints "[1, 2, 3, 4]" 
   println(readOnlyView)     
   readOnlyView.clear()    // ⇒ does not compile  
// gives error  
}

上述代码段将在浏览器中产生以下输出。当我们尝试清除集合的可变列表时,它会报错。

main.kt:9:18: error: unresolved reference: clear
   readOnlyView.clear()    // -> does not compile  
                 ^

在集合中,Kotlin 提供了一些有用的方法,例如first()、last()、filter()等。所有这些方法都是自描述的并且易于实现。此外,Kotlin 在实现集合时遵循与 Java 相同的结构。您可以自由实现任何您选择的集合,例如 Map 和 Set。

在下面的示例中,我们使用不同的内置方法实现了 Map 和 Set。

实时演示
fun main(args: Array<String>) {
   val items = listOf(1, 2, 3, 4)
   println("First Element of our list----"+items.first())
   println("Last Element of our list----"+items.last())
   println("Even Numbers of our List----"+items.
      filter { it % 2 = = 0 })   // returns [2, 4]
   
   val readWriteMap = hashMapOf("foo" to 1, "bar" to 2)
   println(readWriteMap["foo"])  // prints "1"
   
   val strings = hashSetOf("a", "b", "c", "c")
   println("My Set Values are"+strings)
}

上述代码段将在浏览器中产生以下输出。

First Element of our list----1
Last Element of our list----4
Even Numbers of our List----[2, 4]
1
My Set Values are[a, b, c]

范围

范围是 Kotlin 的另一个独特特征。与 Haskell 一样,它提供了一个运算符,可帮助您遍历一个范围。在内部,它是使用rangeTo()实现的,其运算符形式为(..)

在下面的示例中,我们将看到 Kotlin 如何解释此范围运算符。

实时演示
fun main(args: Array<String>) {
   val i:Int  = 2
   for (j in 1..4) 
   print(j) // prints "1234"
   
   if (i in 1..10) { // equivalent of 1 < = i && i < = 10
      println("we found your number --"+i)
   }
}

上述代码段将在浏览器中产生以下输出。

1234we found your number --2

Kotlin - 控制流

在上一章中,我们学习了 Kotlin 系统中可用的不同类型的数据类型。在本章中,我们将讨论 Kotlin 中可用的不同类型的控制流机制。

If - Else

Kotlin 是一种函数式语言,因此与每种函数式语言一样,Kotlin 中的“if”是一个表达式,而不是关键字。表达式“if”会在需要时返回一个值。与其他编程语言一样,“if-else”块用作初始条件检查运算符。在下面的示例中,我们将比较两个变量并相应地提供所需的输出。

实时演示
fun main(args: Array<String>) {
   val a:Int = 5
   val b:Int = 2
   var max: Int
   
   if (a > b) {
      max = a
   } else {
      max = b
   }
   print("Maximum of a or b is " +max)
 
   // As expression 
   // val max = if (a > b) a else b
}

上面这段代码在浏览器中产生以下输出作为结果。我们的示例还包含另一行代码,它描述了如何将“If”语句用作表达式。

Maximum of a or b is 5

When 的使用

如果您熟悉其他编程语言,那么您可能听说过 switch 语句,它基本上是一个条件运算符,当多个条件可以应用于特定变量时。“when”运算符将变量值与分支条件进行匹配。如果满足分支条件,则它将执行该范围内的语句。在下面的示例中,我们将详细了解 Kotlin 中的“when”。

实时演示
fun main(args: Array<String>) {
   val x:Int = 5
   when (x) {
      1 -> print("x = = 1")
      2 -> print("x = = 2")
      
      else -> { // Note the block
         print("x is neither 1 nor 2")
      }
   }
}

上述代码段将在浏览器中产生以下输出。

x is neither 1 nor 2

在上面的示例中,Kotlin 编译器将x的值与给定的分支进行匹配。如果它与任何分支都不匹配,则它将执行 else 部分。实际上,when 等效于多个 if 块。Kotlin 为开发人员提供了另一种灵活性,开发人员可以通过在检查中提供“,”在同一行中提供多个检查。让我们修改上面的示例如下。

实时演示
fun main(args: Array<String>) {
   val x:Int = 5
   when (x) {
      1,2 -> print(" Value of X either 1,2")
      
      else -> { // Note the block
         print("x is neither 1 nor 2")
      }
   }
}

在浏览器中运行相同的代码,它将在浏览器中产生以下输出。

x is neither 1 nor 2

For 循环

循环是一种如此的发明,它提供了遍历任何类型的数据结构的灵活性。与其他编程语言一样,Kotlin 也提供了多种循环方法,但是,其中“For”是最成功的一种。For 循环的实现和使用在概念上类似于 Java for 循环。以下示例显示了如何在现实生活示例中使用它。

实时演示
fun main(args: Array<String>) {
   val items = listOf(1, 2, 3, 4)
   for (i in items) println("values of the array"+i)
}

在上面的代码片段中,我们声明了一个名为“items”的列表,并使用 for 循环遍历该定义的列表并在浏览器中打印其值。以下是输出。

values of the array1
values of the array2
values of the array3
values of the array4

以下是另一个代码示例,我们使用一些库函数使我们的开发工作比以往任何时候都更容易。

实时演示
fun main(args: Array<String>) {
   val items = listOf(1, 22, 83, 4)
   
   for ((index, value) in items.withIndex()) {
      println("the element at $index is $value")
   }
}

一旦我们在我们的编码环境中编译并执行上面的代码片段,它将在浏览器中产生以下输出。

the element at 0 is 1
the element at 1 is 22
the element at 2 is 83
the element at 3 is 4

While 循环和 Do-While 循环

While 和 Do-While 的工作方式与其他编程语言中的工作方式完全相同。这两个循环之间的唯一区别是,在 Do-while 循环的情况下,条件将在循环结束时进行测试。以下示例显示了While 循环的使用。

实时演示
fun main(args: Array<String>) {
   var x:Int = 0
   println("Example of While Loop--")
   
   while(x< = 10) {
      println(x)
      x++
   } 
}

上述代码段将在浏览器中产生以下输出。

Example of While Loop--
0
1
2
3
4
5
6
7
8
9
10

Kotlin 还具有另一个称为 Do-While 循环的循环,其中循环体将执行一次,然后才会检查条件。以下示例显示了Do-while 循环的使用。

实时演示
fun main(args: Array<String>) {
   var x:Int = 0
   do {
      x = x + 10
      println("I am inside Do block---"+x)
   } while(x <= 50)
}

上面的代码片段在浏览器中产生以下输出。在上面的代码中,Kotlin 编译器将执行 DO 块,然后它将转到 while 块中的条件检查。

I am inside Do block---10
I am inside Do block---20
I am inside Do block---30
I am inside Do block---40
I am inside Do block---50
I am inside Do block---60

Return、Break、Continue 的使用

如果您熟悉任何编程语言,那么您一定对帮助我们在应用程序中实现良好控制流的不同关键字有所了解。以下是可用于控制循环或任何其他类型控制流的不同关键字。

Return - Return 是一个关键字,它从被调用函数返回一些值到调用函数。在下面的示例中,我们将使用我们的 Kotlin 编码环境来实现这种情况。

实时演示
fun main(args: Array<String>) {
   var x:Int = 10
   println("The value of X is--"+doubleMe(x))
}
fun doubleMe(x:Int):Int {
   return 2*x;
}

在上面的代码片段中,我们正在调用另一个函数并将输入乘以 2,并将结果值返回到调用函数,即我们的主函数。Kotlin 以不同的方式定义函数,我们将在后续章节中介绍。目前,了解上面代码将在浏览器中生成以下输出就足够了。

The value of X is--20

Continue & Break - Continue 和 break 是逻辑问题中最重要的一部分。“break”关键字在某些条件失败时终止控制器流,而“continue”则执行相反的操作。所有这些操作都立即可见。Kotlin 比其他编程语言更智能,在其中开发人员可以应用多个标签作为可见性。以下代码片段显示了我们如何在 Kotlin 中实现此标签。

实时演示
fun main(args: Array<String>) {
   println("Example of Break and Continue")
   myLabel@ for(x in 1..10) { // appling the custom label
      if(x = = 5) {
         println("I am inside if block with value"+x+"\n-- hence it will close the operation")
         break@myLabel //specifing the label
      } else {
         println("I am inside else block with value"+x)
         continue@myLabel
      }
   }
}

上述代码段将在浏览器中产生以下输出。

Example of Break and Continue
I am inside else block with value1
I am inside else block with value2
I am inside else block with value3
I am inside else block with value4
I am inside if block with value5
-- hence it will close the operation

如您所见,控制器继续循环,直到且仅当x的值为 5 为止。一旦x的值达到 5,它就开始执行 if 块,并且一旦到达 break 语句,整个控制流就会终止程序执行。

Kotlin - 类和对象

在本章中,我们将学习使用 Kotlin 进行面向对象编程 (OOP) 的基础知识。我们将学习类及其对象以及如何操作该对象。根据 OOP 的定义,类是运行时实体的蓝图,而对象是其状态,包括其行为和状态。在 Kotlin 中,类声明包含类头和用花括号括起来的类体,类似于 Java。

Class myClass { // class Header 

   // class Body
}

与 Java 一样,Kotlin 也允许创建类的多个对象,您可以自由地包含其类成员和函数。我们可以使用不同的关键字来控制类成员变量的可见性,我们将在第 10 章“可见性控制”中学习这些关键字。在下面的示例中,我们将创建一个类及其对象,通过该对象我们将访问该类的不同数据成员。

实时演示
class myClass {
   // property (data member)
   private var name: String = "Tutorials.point"
   
   // member function
   fun printMe() {
      print("You are at the best Learning website Named-"+name)
   }
}
fun main(args: Array<String>) {
   val obj = myClass() // create obj object of myClass class
   obj.printMe()
}

上面的代码片段将在浏览器中产生以下输出,我们使用自己的对象调用 myClass 的 printMe()。

You are at the best Learning website Named- Tutorials.point

嵌套类

根据定义,当一个类在另一个类内部创建时,它被称为嵌套类。在 Kotlin 中,嵌套类默认是静态的,因此,无需创建该类的任何对象即可访问它。在下面的示例中,我们将看到 Kotlin 如何解释我们的嵌套类。

实时演示
fun main(args: Array<String>) {
   val demo = Outer.Nested().foo() // calling nested class method
   print(demo)
}
class Outer {
   class Nested {
      fun foo() = "Welcome to The TutorialsPoint.com"
   }
}

上述代码段将在浏览器中产生以下输出。

Welcome to The TutorialsPoint.com

内部类

当嵌套类被标记为“inner”时,它将被称为内部类。内部类可以通过外部类的数据成员进行访问。在下面的示例中,我们将访问外部类的数据成员。

实时演示
fun main(args: Array<String>) {
   val demo = Outer().Nested().foo() // calling nested class method
   print(demo)
}
class Outer {
   private val welcomeMessage: String = "Welcome to the TutorialsPoint.com"
   inner class Nested {
      fun foo() = welcomeMessage
   }
}

上面的代码片段将在浏览器中产生以下输出,我们使用 Kotlin 编译器在编译时提供的默认构造函数调用嵌套类。

Welcome to the TutorialsPoint.com

匿名内部类

匿名内部类是一个非常好的概念,它使程序员的生活变得非常轻松。每当我们实现一个接口时,匿名内部块的概念就会出现。使用运行时对象引用创建接口对象的概念称为匿名类。在下面的示例中,我们将创建一个接口,并使用匿名内部类机制创建该接口的对象。

实时演示
fun main(args: Array<String>) {
   var programmer :Human = object:Human // creating an instance of the interface {
      override fun think() { // overriding the think method
         print("I am an example of Anonymous Inner Class ")
      }
   }
   programmer.think()
}
interface Human {
   fun think()
}

上述代码段将在浏览器中产生以下输出。

I am an example of Anonymous Inner Class 

类型别名

类型别名是 Kotlin 编译器的一个特性。它提供了创建现有类型新名称的灵活性,它不会创建新类型。如果类型名称太长,您可以轻松地引入一个较短的名称并在以后使用中使用它。类型别名对于复杂类型非常有用。在最新版本中,Kotlin 取消了对类型别名的支持,但是,如果您使用的是旧版本的 Kotlin,您可以像下面这样使用它 -

typealias NodeSet = Set<Network.Node>
typealias FileTable<K> = MutableMap<K, MutableList<File>>

Kotlin - 构造函数

在本章中,我们将学习 Kotlin 中的构造函数。Kotlin 有两种类型的构造函数 - 一种是主构造函数,另一种是次构造函数。一个 Kotlin 类可以有一个主构造函数,一个或多个次构造函数。Java 构造函数初始化成员变量,但在 Kotlin 中,主构造函数初始化类,而次构造函数有助于在初始化类时包含一些额外的逻辑。主构造函数可以在类头级别声明,如以下示例所示。

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

在上面的示例中,我们在括号内声明了主构造函数。在这两个字段中,firstName 是只读的,因为它被声明为“val”,而字段 age 可以编辑。在下面的示例中,我们将使用主构造函数。

实时演示
fun main(args: Array<String>) {
   val person1 = Person("TutorialsPoint.com", 15)
   println("First Name = ${person1.firstName}")
   println("Age = ${person1.age}")
}
class Person(val firstName: String, var age: Int) {
}

上面的代码片段将自动初始化这两个变量并在浏览器中提供以下输出。

First Name = TutorialsPoint.com
Age = 15

如前所述,Kotlin 允许为您的类创建一个或多个次构造函数。此次构造函数是使用“constructor”关键字创建的。当您想在 Kotlin 中创建多个构造函数时,或者当您想在主构造函数中包含更多逻辑并且您无法这样做时,这是必需的,因为主构造函数可能会被其他类调用。查看下面的示例,我们在这里创建了一个次构造函数,并使用上面的示例来实现它。

实时演示
fun main(args: Array<String>) {
   val HUman = HUman("TutorialsPoint.com", 25)
   print("${HUman.message}"+"${HUman.firstName}"+
      "Welcome to the example of Secondary  constructor, Your Age is-${HUman.age}")
}
class HUman(val firstName: String, var age: Int) {
   val message:String  = "Hey!!!"
	constructor(name : String , age :Int ,message :String):this(name,age) {
   }
}

注意 - 可以创建任意数量的次构造函数,但是所有这些构造函数都应该直接或间接地调用主构造函数。

上述代码段将在浏览器中产生以下输出。

Hey!!! TutorialsPoint.comWelcome to the example of Secondary  constructor, Your Age is- 25

Kotlin - 继承

在本章中,我们将学习继承。根据定义,我们都知道继承意味着将母类的某些属性累积到子类中。在 Kotlin 中,基类名为“Any”,它是 Kotlin 中声明的“any”默认类的超类。与所有其他 OOPS 一样,Kotlin 也使用一个名为“:”的关键字提供此功能。

Kotlin 中的所有内容默认都是最终的,因此,我们需要在类声明前面使用关键字“open”才能使其允许继承。查看以下继承示例。

实时演示
import java.util.Arrays

open class ABC {
   fun think () {
      print("Hey!! i am thiking ")
   }
}
class BCD: ABC(){ // inheritence happend using default constructor 
}

fun main(args: Array<String>) {
   var  a = BCD()
   a.think()
}

上述代码段将在浏览器中产生以下输出。

Hey!! i am thiking 

现在,如果我们想在子类中覆盖 think() 方法怎么办。然后,我们需要考虑以下示例,我们在这里创建了两个类并在子类中覆盖了其中一个函数。

实时演示
import java.util.Arrays

open class ABC {
   open fun think () {
      print("Hey!! i am thinking ")
   }
}
class BCD: ABC() { // inheritance happens using default constructor 
   override fun think() {
      print("I Am from Child")
   }
}
fun main(args: Array<String>) {
   var  a = BCD()
   a.think()
}

上面的代码片段将调用子类继承的方法,它将在浏览器中产生以下输出。与 Java 一样,Kotlin 也不允许多重继承。

I Am from Child 

Kotlin - 接口

在本章中,我们将学习 Kotlin 中的接口。在 Kotlin 中,接口的工作方式与 Java 8 完全相同,这意味着它们可以包含方法实现以及抽象方法声明。类可以实现接口以使用其定义的功能。我们已经在第 6 章 - “匿名内部类”部分介绍了一个接口示例。在本章中,我们将进一步了解它。“interface”关键字用于在 Kotlin 中定义接口,如以下代码片段所示。

interface ExampleInterface {
   var myVar: String     // abstract property
   fun absMethod()       // abstract method
   fun sayHello() = "Hello there" // method with default implementation
}

在上面的示例中,我们创建了一个名为“ExampleInterface”的接口,并在其中我们总共有几个抽象属性和方法。查看名为“sayHello()”的函数,它是一个已实现的方法。

在下面的示例中,我们将实现上面的接口在一个类中。

实时演示
interface ExampleInterface  {
   var myVar: Int            // abstract property
   fun absMethod():String    // abstract method
   
   fun hello() {
      println("Hello there, Welcome to TutorialsPoint.Com!")
   }
}
class InterfaceImp : ExampleInterface {
   override var myVar: Int = 25
   override fun absMethod() = "Happy Learning "
}
fun main(args: Array<String>) {
   val obj = InterfaceImp()
   println("My Variable Value is = ${obj.myVar}")
   print("Calling hello(): ")
   obj.hello()
   
   print("Message from the Website-- ")
   println(obj.absMethod())
}

上述代码段将在浏览器中产生以下输出。

My Variable Value is = 25
Calling hello(): Hello there, Welcome to TutorialsPoint.Com!
Message from the Website-- Happy Learning 

如前所述,Kotlin 不支持多重继承,但是可以通过一次实现多个接口来实现相同的功能。

在下面的示例中,我们将创建两个接口,然后我们将这两个接口实现到一个类中。

实时演示
interface A {
   fun printMe() {
      println(" method of interface A")
   }
}
interface B  {
   fun printMeToo() {
      println("I am another Method from interface B")
   }
}

// implements two interfaces A and B
class multipleInterfaceExample: A, B

fun main(args: Array<String>) {
   val obj = multipleInterfaceExample()
   obj.printMe()
   obj.printMeToo()
}

在上面的示例中,我们创建了两个示例接口 A、B,并在名为“multipleInterfaceExample”的类中,我们实现了前面声明的两个接口。上面的代码片段将在浏览器中产生以下输出。

method of interface A
I am another Method from interface B

Kotlin - 可见性控制

在本章中,我们将学习 Kotlin 语言中可用的不同修饰符。访问修饰符用于限制应用程序中使用的变量、方法和类的使用。与其他 OOP 编程语言一样,此修饰符适用于多个位置,例如类头或方法声明。Kotlin 中有四种访问修饰符可用。

私有

类、方法和包可以使用 private 修饰符声明。一旦任何内容被声明为 private,那么它只能在其直接作用域内访问。例如,私有包可以在该特定文件中访问。私有类或接口只能被其数据成员访问,等等。

private class privateExample {
   private val i = 1
   private val doSomething() {
   }
}

在上面的示例中,类“privateExample”和变量 i 都只能在同一个 Kotlin 文件中访问,因为它们都在声明块中声明为 private。

Protected

Protected 是 Kotlin 的另一个访问修饰符,目前它不适用于顶级声明,例如任何包都不能是 protected。受保护的类或接口仅对其子类可见。

class A() {
   protected val i = 1
}
class B : A() {
   fun getValue() : Int {
      return i
   }
}

在上面的示例中,变量“i”声明为 protected,因此,它仅对其子类可见。

Internal

Internal 是 Kotlin 中引入的一个新的修饰符。如果任何内容被标记为 internal,那么该特定字段将位于内部字段中。内部包仅在其实现的模块内部可见。内部类接口仅对存在于同一包或模块中的其他类可见。在以下示例中,我们将看到如何实现内部方法。

class internalExample {
   internal val i = 1
   internal fun doSomething() {
   }
}

在上面的示例中,名为“doSomething”的方法和变量被标记为 internal,因此,这两个字段只能在声明它们的包内部访问。

Public

Public 修饰符可以在项目工作区的任何地方访问。如果未指定访问修饰符,则默认情况下它将处于 public 作用域。在我们之前的所有示例中,我们都没有提到任何修饰符,因此,它们都处于 public 作用域。以下是一个示例,以了解有关如何声明公共变量或方法的更多信息。

class publicExample {
   val i = 1
   fun doSomething() {
   }
}

在上面的示例中,我们没有提到任何修饰符,因此所有这些方法和变量默认都是 public 的。

Kotlin - 扩展

在本章中,我们将学习 Kotlin 的另一个新特性“扩展”。使用扩展,我们将能够添加或删除某些方法功能,即使不继承或修改它们。扩展是静态解析的。它实际上并没有修改现有的类,而是创建一个可调用的函数,可以通过点运算符调用。

函数扩展

在函数扩展中,Kotlin 允许在主类之外定义方法。在以下示例中,我们将看到如何在函数级别实现扩展。

实时演示
class Alien {
   var skills : String = "null"
	
   fun printMySkills() {
      print(skills)
   }		
}
fun main(args: Array<String>) {
   var  a1 = Alien()
   a1.skills = "JAVA"
   //a1.printMySkills()
	
   var  a2 = Alien()
   a2.skills = "SQL"
   //a2.printMySkills()
	
   var  a3 = Alien()
   a3.skills = a1.addMySkills(a2)
   a3.printMySkills()
}
fun Alien.addMySkills(a:Alien):String{
   var a4 = Alien()
   a4.skills = this.skills + " " +a.skills
   return a4.skills
}

在上面的示例中,“Alien”类中没有任何名为“addMySkills()”的方法,但是,我们仍然在类外部的其他地方实现了相同的方法,这就是扩展的魔力。

上面的代码将在浏览器中生成以下输出。

JAVA SQL

对象扩展

Kotlin 提供了另一种实现 Java 静态功能的机制。这可以通过使用关键字“companion object”来实现。使用这种机制,我们可以在工厂方法内部创建类的对象,然后我们可以使用类名的引用来调用该方法。在以下示例中,我们将创建一个“companion object”。

实时演示
fun main(args: Array<String>) {
   println("Heyyy!!!"+A.show())
}
class A {
   companion object {
      fun show():String {
         return("You are learning Kotlin from TutorialsPoint.com")
      }
   }
}

上述代码段将在浏览器中产生以下输出。

Heyyy!!! You are learning Kotlin from TutorialsPoint.com

上面的示例看起来像 Java 中的静态方法,但是,在实际运行时,我们正在创建作为同一类成员变量的对象。这就是为什么它也包含在扩展属性下,并且可以替代地称为对象扩展。您基本上是在扩展同一类的对象以使用某些成员函数。

Kotlin - 数据类

在本章中,我们将进一步了解 Kotlin 编程语言的数据类。当类被标记为“data”时,它可以被标记为数据类。这种类型的类可以用来保存基本数据。除此之外,它不提供任何其他功能。

所有数据类都需要有一个主构造函数,并且所有主构造函数都必须至少有一个参数。每当一个类被标记为数据类时,我们可以使用该数据类的一些内置函数,例如“toString()”、“hashCode()”等。任何数据类都不能有像 abstract 和 open 或 internal 这样的修饰符。数据类也可以扩展到其他类。在以下示例中,我们将创建一个数据类。

实时演示
fun main(args: Array<String>) {
   val book: Book = Book("Kotlin", "TutorialPoint.com", 5)
   println("Name of the Book is--"+book.name) // "Kotlin"
   println("Puclisher Name--"+book.publisher) // "TutorialPoint.com"
   println("Review of the book is--"+book.reviewScore) // 5
   book.reviewScore = 7
   println("Printing all the info all together--"+book.toString()) 
   //using inbuilt function of the data class 
   
   println("Example of the hashCode function--"+book.hashCode())
}

data class Book(val name: String, val publisher: String, var reviewScore: Int)

上面的代码将在浏览器中产生以下输出,其中我们创建了一个数据类来保存一些数据,并且从主函数中我们访问了其所有数据成员。

Name of the Book is--"Kotlin"
Puclisher Name--"TutorialPoint.com"
Review of the book is--5
Printing all the info all together--(name-Kotlin, publisher-TutorialPoint.com, reviewScore-7)
Example of the hashCode function---1753517245

Kotlin - 密封类

在本章中,我们将学习另一种称为“Sealed”类的类类型。这种类型的类用于表示受限的类层次结构。Sealed 允许开发人员维护预定义类型的数据类型。要创建一个密封类,我们需要使用关键字“sealed”作为该类的修饰符。密封类可以有自己的子类,但所有这些子类都需要与密封类一起在同一个 Kotlin 文件中声明。在以下示例中,我们将看到如何使用密封类。

实时演示
sealed class MyExample {
   class OP1 : MyExample() // MyExmaple class can be of two types only
   class OP2 : MyExample()
}
fun main(args: Array<String>) {
   val obj: MyExample = MyExample.OP2() 
   
   val output = when (obj) { // defining the object of the class depending on the inuputs 
      is MyExample.OP1 -> "Option One has been chosen"
      is MyExample.OP2 -> "option Two has been chosen"
   }
   
   println(output)
}

在上面的示例中,我们有一个名为“MyExample”的密封类,它只有两种类型 - 一种是“OP1”,另一种是“OP2”。在主类中,我们在类中创建一个对象并在运行时分配其类型。现在,由于此“MyExample”类是密封的,因此我们可以在运行时应用“when”子句来实现最终输出。

在密封类中,我们不需要使用任何不必要的“else”语句来使代码复杂化。上面的代码将在浏览器中产生以下输出。

option Two has been chosen

Kotlin - 泛型

与 Java 一样,Kotlin 提供了更高阶的变量类型,称为泛型。在本章中,我们将学习 Kotlin 如何实现泛型以及作为开发人员我们如何使用泛型库中提供的那些功能。在实现方面,泛型与 Java 非常相似,但 Kotlin 开发人员引入了两个新关键字“out”“in”,使 Kotlin 代码更具可读性,并方便开发人员使用。

在 Kotlin 中,类和类型是完全不同的概念。根据示例,List 是 Kotlin 中的一个类,而 List<String> 是 Kotlin 中的一个类型。以下示例描述了 Kotlin 中泛型的实现方式。

fun main(args: Array<String>) {
   val integer: Int = 1
   val number: Number = integer
   print(number)
}

在上面的代码中,我们声明了一个“integer”,然后我们将该变量分配给一个数字变量。这是可能的,因为“Int”是 Number 类的子类,因此类型转换在运行时自动发生并产生输出“1”。

让我们进一步了解 Kotlin 中的泛型。当我们不确定将在应用程序中使用的数据类型时,最好使用泛型数据类型。通常,在 Kotlin 中,泛型由<T>定义,其中“T”代表模板,它可以由 Kotlin 编译器动态确定。在以下示例中,我们将看到如何在 Kotlin 编程语言中使用泛型数据类型。

实时演示
fun main(args: Array<String>) {
   var objet = genericsExample<String>("JAVA")
   var objet1 = genericsExample<Int>(10)
}
class genericsExample<T>(input:T) {
   init {
      println("I am getting called with the value "+input)
   }
}

在上面的代码片段中,我们正在创建一个具有泛型返回类型的类,它表示为<T>。看看 main 方法,我们在运行时动态定义了它的值,在创建该类的对象时提供了值类型。这就是 Kotlin 编译器如何解释泛型的。当我们在代码环境中运行此代码时,将在浏览器中获得以下输出。

I am getting called with the value JAVA
I am getting called with the value 10

当我们想要将泛型类型分配给其任何超类型时,我们需要使用“out”关键字,当我们想要将泛型类型分配给其任何子类型时,我们需要使用“in”关键字。在以下示例中,我们将使用“out”关键字。同样,您可以尝试使用“in”关键字。

实时演示
fun main(args: Array<String>) {
   var objet1 = genericsExample<Int>(10)
   var object2 = genericsExample<Double>(10.00)
   println(objet1)
   println(object2)
}
class genericsExample<out T>(input:T) {
   init {
      println("I am getting called with the value "+input)
   }
}

上面的代码将在浏览器中产生以下输出。

I am getting called with the value 10
I am getting called with the value 10.0
genericsExample@28d93b30
genericsExample@1b6d3586

Kotlin - 委托

Kotlin 通过引入一个新的关键字“by”来支持“委托”设计模式。使用此关键字或委托方法,Kotlin 允许派生类通过特定对象访问接口的所有已实现的公共方法。以下示例演示了 Kotlin 中是如何发生的。

实时演示
interface Base {
   fun printMe() //abstract method
}
class BaseImpl(val x: Int) : Base {
   override fun printMe() { println(x) }   //implementation of the method
}
class Derived(b: Base) : Base by b  // delegating the public method on the object b

fun main(args: Array<String>) {
   val b = BaseImpl(10)
   Derived(b).printMe() // prints 10 :: accessing the printMe() method 
}

在示例中,我们有一个接口“Base”,其抽象方法名为“printme()”。在 BaseImpl 类中,我们实现了这个“printme()”,然后从另一个类中使用“by”关键字使用此实现。

上述代码段将在浏览器中产生以下输出。

10

属性委托

在上一节中,我们学习了使用“by”关键字的委托设计模式。在本节中,我们将学习如何使用 Kotlin 库中提到的某些标准方法来委托属性。

委托意味着将责任传递给另一个类或方法。当属性已在某些地方声明时,我们应该重用相同的代码来初始化它们。在以下示例中,我们将使用 Kotlin 提供的一些标准委托方法和一些标准库函数在我们的示例中实现委托。

使用 Lazy()

Lazy 是一个 lambda 函数,它将属性作为输入,并返回Lazy<T>的实例,其中<T>基本上是它正在使用的属性的类型。让我们看看以下内容以了解其工作原理。

实时演示
val myVar: String by lazy {
   "Hello"
}
fun main(args: Array<String>) {
   println(myVar +" My dear friend")
}

在上面的代码片段中,我们将变量“myVar”传递给 Lazy 函数,该函数依次将值分配给其对象并将相同的值返回给主函数。以下是浏览器中的输出。

Hello My dear friend

Delegetion.Observable()

Observable() 接受两个参数来初始化对象,并将相同的值返回给被调用函数。在以下示例中,我们将看到如何使用 Observable() 方法来实现委托。

实时演示
import kotlin.properties.Delegates
class User {
   var name: String by Delegates.observable("Welcome to Tutorialspoint.com") {
      prop, old, new ->
      println("$old -> $new")
   }
}
fun main(args: Array<String>) {
   val user = User()
   user.name = "first"
   user.name = "second"
}

上述代码段将在浏览器中产生以下输出。

first -> second

一般来说,“by”关键字后的表达式是委托的。变量pget()set()方法将被委托给在 Delegate 类中定义的getValue()setValue()方法。

class Example {
   var p: String by Delegate()
}

对于上面的代码片段,以下是我们需要生成的委托类,以便在变量p中分配值。

class Delegate {
   operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
      return "$thisRef, thank you for delegating '${property.name}' to me!"
   }
   operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
      println("$value has been assigned to '${property.name} in $thisRef.'")
   }
}

在读取时,将调用 getValue() 方法,而在设置变量时,将调用 setValue() 方法。

Kotlin - 函数

Kotlin 是一种静态类型语言,因此函数在其中发挥着重要作用。我们非常熟悉函数,因为我们在整个示例中都在使用函数。函数用关键字“fun”声明。像任何其他 OOP 一样,它也需要一个返回类型和一个可选的参数列表。

在以下示例中,我们定义了一个名为 MyFunction 的函数,并在主函数中调用此函数并传递一些参数。

实时演示
fun main(args: Array<String>) {
   println(MyFunction("tutorialsPoint.com"))
}
fun MyFunction(x: String): String {
   var c:String  = "Hey!! Welcome To ---"
   return (c+x)
}

上述代码段将在浏览器中产生以下输出。

Hey!! Welcome To ---tutorialsPoint.com

函数应按如下方式声明:

fun <nameOfFunction>(<argument>:<argumentType>):<ReturnType>

以下是 Kotlin 中一些不同类型的函数。

Lambda 函数

Lambda 是一种高级函数,在声明函数和定义函数时可以大幅减少样板代码。Kotlin 允许你定义自己的 Lambda。在 Kotlin 中,你可以声明你的 Lambda 并将其传递给一个函数。

请看下面的例子。

实时演示
fun main(args: Array<String>) {
   val mylambda :(String)->Unit  = {s:String->print(s)}
   val v:String = "TutorialsPoint.com"
   mylambda(v)
}

在上面的代码中,我们创建了自己的 Lambda,名为“mylambda”,并将一个变量传递给了这个 Lambda,该变量的类型为 String,值是“TutorialsPoint.com”。

上述代码段将在浏览器中产生以下输出。

TutorialsPoint.com

内联函数

上面的例子展示了我们可以在 Kotlin 应用程序中使用的 Lambda 表达式的基本用法。现在,我们可以将 Lambda 传递给另一个函数以获取输出,这使得调用函数成为内联函数。

请看下面的例子。

实时演示
fun main(args: Array<String>) {
   val mylambda:(String)->Unit  = {s:String->print(s)}
   val v:String = "TutorialsPoint.com"
   myFun(v,mylambda) //passing lambda as a parameter of another function 
}
fun myFun(a :String, action: (String)->Unit) { //passing lambda 
   print("Heyyy!!!")
   action(a)// call to lambda function
}

上面的代码将在浏览器中产生以下输出。使用内联函数,我们传递了一个 Lambda 作为参数。任何其他函数都可以使用“inline”关键字将其设置为内联函数。

Heyyy!!!TutorialsPoint.com

Kotlin - 解构声明

Kotlin 包含其他编程语言的许多特性。它允许你同时声明多个变量。这种技术称为解构声明。

以下是解构声明的基本语法。

val (name, age) = person

在上面的语法中,我们创建了一个对象并在单个语句中一起定义了它们。稍后,我们可以按如下方式使用它们。

println(name)
println(age)

现在,让我们看看如何在实际应用中使用它。考虑以下示例,我们创建了一个包含一些属性的 Student 类,稍后我们将使用它们来打印对象的值。

实时演示
fun main(args: Array<String>) {
   val s = Student("TutorialsPoint.com","Kotlin")
   val (name,subject) = s
   println("You are learning "+subject+" from "+name)
}
data class Student( val a :String,val b: String ){
   var name:String = a
   var subject:String = b
}

上述代码段将在浏览器中产生以下输出。

You are learning Kotlin from TutorialsPoint.com

Kotlin - 异常处理

异常处理是编程语言中非常重要的一部分。此技术可以防止应用程序在运行时生成错误的输出。在本章中,我们将学习如何在 Kotlin 中处理运行时异常。Kotlin 中的异常与 Java 中的异常非常相似。所有异常都是“Throwable”类的子类。以下示例展示了如何在 Kotlin 中使用异常处理技术。

fun main(args: Array<String>) {
   try {
      val myVar:Int = 12;
      val v:String = "Tutorialspoint.com";
      v.toInt();
   } catch(e:Exception) {
      e.printStackTrace();
   } finally {
      println("Exception Handeling in Kotlin");
   }
}

在上面的代码片段中,我们声明了一个字符串,然后将其转换为整数,这实际上是一个运行时异常。因此,我们将在浏览器中得到以下输出。

val myVar:Int = 12;
Exception Handeling in Kotlin

注意 - 与 Java 一样,Kotlin 也会在执行 catch 块后执行 finally 块。

广告