从java到Kotlin学习三:类 对象 和接口

相比较java来说 没有太大改变 我们一起来看下  这章节我不在粘java的例子了 但是 会做简单总结 这样大家能看的更明确一点 

接口

java 

public interface _Clickable {
    void click();
}

public class _ClickAbleImpl implements _Clickable{
    @Override
    public void click() {


    }
}

kotlin


kotlin 默认public 同时 能够包含非抽象方法 但是 该方法必须被显示实现 否则会报错(kotlin 强制要求提供自己的实现)


class ClickableImpl:Clickable{
    override fun click() {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

  override fun getName():String {

       super.getName()

}

}

kotlin使用 : 来代替 implements  和 extends  其他基本一致  

修饰符

java

    class 和 method 默认修饰符是 open  就是我们能够为该class 创建子类 并且重写需要的方法   除非我们使用finial来修饰

kotlin 

    class和method 默认是close  就是默认使用finial修饰  如果想继承和重写 必须使用open 修饰 class和method  我们同样        可以显示的使用finial来禁止method被重写

    类中修饰符意义

     finial : 不能被重写  类中成员默认使用

     open:   可以被重写 需要显示声明

     abstract : 必须被重写 

    可见性修饰符

       public private  protected  这三个和java是一样的 

       internal  只在模块中可见(kotlin特有的)--模块 即 一组一起编译的文件 我理解就是model

内部类和嵌套类 (默认是嵌套类)

 内部类 默认持有外部类对象的引用   嵌套类 不持有外部类对象的引用  

这两个是什么意思呢 ?

      java: 

          内部类:    class B{...}          嵌套类:(静态内部类):  classB{...}

                            class A{...}                                                     static class A{...}

                           

                           

       kotlin :

          内部类 :class B{...}                  嵌套类:    class B{...}

                         inner  class A{...}                      class  A{....}

                     

        如果想从inner class 访问 ouer class  那么需要使用this@outer 来获取外部类对象 

    密封类

          kotlin 特有概念   能够限制子类数量的 类    

           对于接口类 InterA  我们想 只要两个子类 classA :InterA    class _A  :InterA  这时候我们就可以使用密封类 scale 

          

 scale class InterA{

               classA :InterA   {...}

              class _A  :InterA {...}

            }  

            注:子类必须卸载接口类里面(1.1中已经去掉了这个限制)  前面我们说过对于class 和method默认是close 不支持                       继 承和重写 但是 scale 默认是open  

     类的声明 

          前面我们已经说过继承或者实现一个类 我们使用  :来替代implement  和 extends  那么下面我们看下类的初始化以及声明            

  主构造方法:

         在kotlin中我们可以使用   class A constructor (val name:String)    来定义一个类  没有任何方法体  

         这样声明就相当于java中 class A {  public A(String name){}} 也就是后面加上() 就代表了我们的构造方法 

         这样的构造方法称为主构造方法 constructor 可以省略 class A (val name:String)

         我们看下 构造方法中的参数是怎么工作的

      

     class A(val name :String){

                  val _name:String

                  init{ _name=name}  //初始化语句 

          }

        construct :声明构造方法 (无论主构造或者是从构造)

        init :引入初始化块  类被创建的时候执行  

         val:表示会被初始化value初始化 

      java:默认实现无参构造 

      kotlin  : open class A   我们这样定义一个类 表示该类只有一个无参构造方法  但是如果我们继承该类 必须显示调用A()

               class B:A()   

      注意:kotlin 和java一样 接口是没有构造方法的 所以 实现接口不需要加()

多种构造方式

      

 open class View{

             constructor(ctx:Context){...}

             constructor(ctx:Context,attr:Int){...}

         }

上面的demo中没有主构造方法 只有两个从构造方法  

我们来继承下 该类

    

class MyView :View{

         constructor (ctx:Context) :this(ctx,0)

          constructor(ctx:Context,attr:Int):super(ctx:Context,attr:Int){}

     }

这个是不是比较熟悉 我们java 自定义View中经常这么写  一个参的构造方法 委托当前类中两个参的实现 两个参的委托View中的默认实现 

注:如果类没有主构造方法 那么每个从构造方法必须初始化 基类  或者委托给初始化了基类的构造方法 

数据类:

   java 中 我们通常需要手动实现 equals 和 toString  

   kotlin中 帮助我们实现了这些通用方法  

      data class User(val name :String,val age:Int)  

     注:数据类的参数类型 最好是val  虽然 var 也可以 但是很有可能在线程中 被修改值  

     为了更方便val 的数据操作  kotlin 生成了一个方法  copy  这样我们就可以手动修改值了

     val Bob=User("Bob",0)

     Bob.copy(age=18)

     copy有单独的生命周期 并不会影响原始实例的位置 很方便修改  

     手动实现copy

      

     class User(val name :String,val age:Int){

               ...

                 fun copy(name:String=this.name,age:Int=this.age)=User(name,age)

           }

委托类(by)

     我们使用继承实现某个类的时候 必须实现里面所有的抽象方法  但是很多方式我们根本不需要  或者是完全可以使用默认实现  我们只想修改我们需要的就好了   那么我们看下 demo 

class DelegationCollection(innerList:ArrayList<SimpleDemoUtils.User>) :Collection<SimpleDemoUtils.User> {
    override val size: Int
        get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
    override fun contains(element: SimpleDemoUtils.User): Boolean {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
    override fun containsAll(elements: Collection<SimpleDemoUtils.User>): Boolean {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
    override fun isEmpty(): Boolean {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }
    override fun iterator(): Iterator<SimpleDemoUtils.User> {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }}

  害怕   我们看下 使用委托 之后   世界都安静了  为什么不用实现了呢 因为我们将实现 全部委托给了 innerList  而innerList是ArrayList  本身就已经继承自 Collection 实现了所有抽象方法了 

class DelegationCollection(innerList: ArrayList<SimpleDemoUtils.User>) : Collection<SimpleDemoUtils.User> by innerList {}

 那么我们只需要修改我们需要的就好了  我们写个完成的demo 

/**
 * @author zhangyanjiao
 * @desc  我们想统计下 add 进来的元素个数
 *   hash 过滤重复元素  所以添加个数 和 真正添加进去的个数不完全相同  ok  我们测下
 */
class DelegationCollection<T>(val innerList:MutableCollection<T> = HashSet()) : MutableCollection<T> by innerList {

    var addCount: Int = 0
    override fun add(element: T): Boolean {
        addCount++
        return innerList.add(element)
    }

    override fun addAll(elements: Collection<T>): Boolean {
        addCount += elements.size
        return innerList.addAll(elements)
    }
}


class ClickableImpl:Clickable{
    override fun click() {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

  override fun getName():String {

       super.getName()

}

}

class ClickableImpl:Clickable{
    override fun click() {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

  override fun getName():String {

       super.getName()

}

}

 private fun delegation() {
        val map = DelegationCollection<Int>()
        map.addAll(listOf(1, 1, 2, 3))
        Log.d("SecondActivity", "add count=${map.addCount},remain count =${map.size}")
    }
结果 
interface Clickable {
    fun click()

    fun getName():String="Clickable "

}

 D/SecondActivity: add count=4,remain count =3

object 关键字 

    使用场景

  • 对象声明 是定义单例的一种方式
  • 伴生对象可以支持工厂和其他与这个类相关 但调用时并不依赖实例的方法 成员可以通过类名来访问
  • 对象表达式 用来替代java的匿名内部类 

 单例 实现

object MyUtils{
   fun add(a:Int,b:Int){
       return a+b 
   }
}

   调用方式:

MyUtils.add(1,2)

伴生对象(工厂方法 和静态成员 的实现)

kotlin 不能拥有静态成员,但是之前我们说顶层函数和成员 相当于静态来使用   但是顶层函数不能访问类的私有成员 。(也就是私有成员不能再类外部的顶层函数中使用)

那么此时我们就可以用工厂方法来解决

companion :标记对象 可以直接通过容器名直接访问这个对象的方法和属性 不需要显示制定对象名称(很像static 方法调用)

class A{
    companion object{
       fun foo(){
          ...
         }
    }
}

调用

A.foo()

使用工厂方法代替从构造方法 

class User(val name:String){
   companion object{
       fun newSubUserScribing(email:String){
            return User(email)
       }
   }
}

对象表达式:匿名内部类

java

 
class A{
   btView.setOnclickListener(new OnClickListener(){
     ...})
}

kotlin

class A{
   btView.setOnclickListener(object:OnclickListener(){...})
}

使用object声明并创建了一个实例 但是该实例并没有名称  只是实现OnCLickListener  在java中 匿名内部类 只能实现一个接口 但是kotlin中能够实现多个 

关于对象表达式 我们会在下一章具体说 这里先跳过~


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值