About Kotlin-Kotlin中的类2About Kotlin(2)

About Kotlin(2)

继续昨天的部分。介绍Kotlin中的类。

Kotlin中的类

抽象类和接口

抽象类

跟Java一样,使用abstract关键字

open class Base{
  open fun f(){}
}
abstract class Derived:Base(){
  override abstract fun f()
}
接口
//内部可以直接写实现
interface MyInterface{
  fun bar()
  fun foo(){    //默认实现
    println("foo")
  }
}

//接口中可以写属性。不允许初始化。实现类必须初始化
interface MyInterface2{
  var name:String //抽象
}
class MyImpl:MyInterface2{
  override var name:String="override name" //重载属性
}

密封类

使用sealed修饰符修饰。其实是一组类的集合。可以用来表示受限的类的继承结构。 其也可以有子类,所有子类也必须在相同的文件中声明。 密封类从某种意义上说,它们是枚举类的扩展:枚举类型的值集也受到限制,但每个枚举常量仅作为单个实例存在,而密封类的子类可以包含多个实例并包含状态。这样又具备了枚举不具备的灵活性。

sealed class BaseClass {

    class Test1 : BaseClass() {
        override fun test() {
            println("Test1实例")
        }

    }
    class Test2 : BaseClass() {
        override fun test() {
            println("Test2实例")
        }
    }
    object Test3 : BaseClass() {
        override fun test() {
            println("Test3实例")
        }
    }
    open fun test() {
        println("BaseClass实例")
    }
}

fun test(instance: BaseClass)=when(instance){
    is BaseClass.Test1-> instance.test()
    is BaseClass.Test2-> instance.test()
    is BaseClass.Test3->instance.test()
}

fun main(str: Array<String>) {
    test( BaseClass.Test1() )
    test( BaseClass.Test2() )
    test( BaseClass.Test3 )
}

内部类

inner标记

使用inner标记才能够访问外部类的变量

class Outer{
  private val bar:Int = 1
  inner class Inner{
    fun foo()=bar
  }
}
//调用的方式.和java类的内部类调用的方式相同
val demo = Outer().Inner().foo()

嵌套类

不用inner标记,直接写在类的内部的类,在kotlin中称为所谓的嵌套类

class Outer{
   private val bar: Int = 1
   class Nested{
     fun foo()=2
   }
}
//嵌套类的调用有点像静态内部类。
val demo = Outer.Nested().foo()

枚举类

枚举类最基本的用法是实现类型安全的枚举

enum class Direction{
  NORTH,SOUTH,WEST,EAST
}
//和Java一样,每个枚举类都是枚举的实例,可以被初始化
enum class Color(val rgb:Int){
  RED(0xFF0000),
  GREEN(0x00FF00),
  BLUE(0x0000FF)
}

匿名类

enum class ProtocolState{
  WAITING{
    override fun signal()=WAITING
  },
  TALKING{
    override fun signal()=TALKING
  };//这里需要用分号分割
  abstract fun signal():ProtocolState
}

Object类(及匿名类)

在Kotlin中使用对象表达式对象声明进行表示

对象表达式(匿名类)

匿名类其实就是在Java中的匿名内部类。 java中调用方法时,提供的匿名内部类

fun countClicks(window:JComponent){
  var clickCount = 0
  val enterCount=0
  
  //通常的情况,使用Object开头就可以
window.addMouseListener(object:MouseAdapter()){
  override fun mouseClicked(e:MouseEvent){
    //与Java不同的是,甚至可以直接访问变量。(未被final修饰)!
    clickCount++
    enterCount++
  }
  ...
}
}

//多个超类的情况
open class A(x:Int){
  public open val y:Int=x
}
interface B{...}
val ab :A=object:A(1),B{
  override val y = 15
}

//如果只是需要一个对象,什么都不需要的话。也可以直接写
fun foo(){
  val adHoc = object{
    var x:Int = 0
    var y:Int =0
  }
  println(adHoc.x+adHoc.y)
}

这里有一点值得特别注意的的是: 匿名对象可以用作只在本地私有作用域中声明的类型。只能做为私有函数的返回值。

class C{
  //私有函数,所以其返回雷士的对象是匿名对象
    private fun foo()=object{
        val x :String="x"
    }
  //默认都是public final的方法.使用对象声明返回的类型是Any
    fun publicFoo()=object{
        val x:String="x"
    }
  
    fun bar(){
        val x1= foo().x //可以直接访问
        val x2= publicFoo().x //错误!未能解析的引用"x"
    }
}

对象声明

单例

是指使用object关键字声明的一种类。这种类是单例,并且所有的成员都是静态方法。

object DataProviderManager{
  fun registerDataProvider(provider:DataProvider){}
}
伴生对象

类内部的对象声明可以使用companion关键字标记

class MyClass{
//就是静态内部类咯?但是每个类的伴生对象只能有一个!?
  companion object Factory{
    fun create():MyClass=MyClass()
  }
}

//调用方式类似于Java中的静态方法
val instance = MyClass.create()

//如果按照下列写法,调用时,可以使用名称 Companion
class MyClass{
  companion object{}
}

val x = MyClass.Companion

这里需要注意的是:

在 JVM 平台,只有使用 @JvmStatic 注解,才能将伴生对象的成员生成为真正的静态方法和字段。否则,都只是实例变量

//即使伴生对象的成员看起来像其他语言的静态成员,在运行时他们仍然是真实对象的实例成员,而且,例如还可以实现接口:
interface Factory<T> {
    fun create(): T
}
class MyClass {
    companion object : Factory<MyClass> {
      //注意需要写Override
        override fun create(): MyClass = MyClass()
    }
}
//当然,在 JVM 平台,如果使用 @JvmStatic 注解,你可以将伴生对象的成员生成为真正的静态方法和字段。
//@JvmStatic 注解也可以应用于对象或伴生对象的属性, 使其 getter 和 setter 方法在该对象或包含该伴生对象的类中是静态成员。更多详细的内容之后再看
class MyClassJVM {
     companion object : Factory<MyClassJVM> {
       @JvmStatic override fun create(): MyClassJVM = MyClassJVM()
    }
}

到这里,就大概把Kotin中的类汇总完了。接下来,也还是会按照参考文章的这个思路。记录Kotlin中的属性。方法。修饰符。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏xx_Cc的学习总结专栏

iOS-正则表达式的简单使用

47670
来自专栏blackheart的专栏

[C#3] 1-扩展方法

1.从DEMO开始 先看一个扩展方法的例子: 1 class Program 2 { 3 public static void Main(...

223100
来自专栏菜鸟前端工程师

JavaScript学习笔记023-对象方法0包装对象0静态属性

10920
来自专栏web前端-

JavaScript运算符和控制语句

语法: switch(n)  {      case 1:      执行代码块 1      break;      case 2:      执行代码块 2...

9720
来自专栏Java3y

给女朋友讲解什么是Optional【JDK 8特性】

前两天带女朋友去图书馆了,随手就给她来了一本《与孩子一起学编程》的书,于是今天就给女朋友讲解一下什么是Optional类。

7930
来自专栏程序员宝库

如何用JavaScript手动实现一个栈

在生活中也能发现很多栈的例子。例如,厨房里堆放的盘子,总是叠在上方的先被使用;输入框内容进行删除时,总是最后输入的先删除;弹夹中的子弹,越后装入的,越先发射.....

12940
来自专栏趣谈编程

Unicode与UTF-8的区别

要弄清Unicode与UTF-8的关系,我们还得从他们的来源说起,下来我们从刚开始的编码说起,直到Unicode的出现,我们就会感觉到他们之间的关系

14220
来自专栏一个会写诗的程序员的博客

函数式编程与面向对象编程[1]: Lambda表达式 函数柯里化 高阶函数函数式编程与面向对象编程[1]: Lambda表达式 函数柯里化 高阶函数.md

For example, in Lisp the 'square' function can be expressed as a lambda expressi...

8320
来自专栏偏前端工程师的驿站

JS魔法堂:再识Number type

Brief                                   本来只打算理解JS中0.1 + 0.2 == 0.300000000000000...

23950
来自专栏大数据钻研

js中call、apply、bind那些事

前言 回想起之前的一些面试,几乎每次都会问到一个js中关于call、apply、bind的问题,比如… 怎么利用call、apply来求一个数组中最大或者最小值...

31250

扫码关注云+社区

领取腾讯云代金券