Kotlin核心编程(七)

2023-11-19

Kotlin核心编程(七)

多继承问题

接口实现多继承问题

interface Flyer{
    fun fly()
    fun kind()= "flying animals Flyer"
}
interface Animal{
    val name:String
    fun eat()
    fun kind()="fly animals Animal"
}
class Bird(override val name: String):Flyer,Animal{
    override fun fly() {
        println("i am fly")
    }

    override fun kind() = super<Flyer>.kind()  // super关键字,我们
    // 可以利⽤它来指定继承哪个⽗接⼜的⽅法,

    override fun eat() {
        println("i am eat")
    }

}
fun main(args:Array<String>){
    val bird = Bird("sparrow")
    println(bird.kind())
}

//=======================================
interface Flyer{
    fun fly()
    fun kind()= "flying animals Flyer"
}
interface Animal{
    val name:String
    fun eat()
    fun kind()="fly animals Animal"
}
class Bird(override val name: String):Flyer,Animal{
    override fun fly() {
        println("i am fly")
    }

    override fun kind() = "a flying $name" /*。当然我们也可以主动实现⽅法,
    覆盖⽗接的⽅法。*/

    override fun eat() {
        println("i am eat")
    }

}
fun main(args:Array<String>){
    val bird = Bird("sparrow")
    println(bird.kind())
}
/*
1)在Kotlin中实现⼀个接⼜时,需要实现接⼜中没有默认实现的
⽅法及未初始化的属性,若同时实现多个接⼜,⽽接⼜间又有相同⽅
法名的默认实现时,则需要主动指定使⽤哪个接⼜的⽅法或者重写⽅
法;
2) 如 果 是 默 认 的 接 ⼜ ⽅ 法, 你 可 以 在 实 现 类 中 通 过
“ super<T>” 这种⽅式调⽤它,其中T为拥有该⽅法的接⼜名;
3)在实现接⼜的属性和⽅法时,都必须带上override关键字,不
能省略。*/

/*
通过val声明的构造⽅法参数,其实是在类内部定义了⼀个同名的属性,所以我们当然
还可以把name的定义放在Bird类内部
*/
class Bird(name: String):Flyer,Animal{
   
    override val name : String  // override不能少
    init {
        this.name=name
    }

    override fun fly() {
        println("i am fly")
    }

    override fun kind() = "a flying $name" /*。当然我们也可以主动实现⽅法,
    覆盖⽗接的⽅法。*/

    override fun eat() {
        println("i am eat")
    }
}
// 也可使用get方法,初始化name
override val name: String
        get() = name

getter和setter

你在声明⼀个类的属性时,要知道背后Kotlin编译器也帮你⽣成了getter和setter⽅法。当然你也可以主动声明这两个⽅法来实现⼀些特殊的逻辑。还有以下两点需要注意:

  1. ⽤val声明的属性将只有getter⽅法,因为它不可修改;⽽⽤var修饰的属性将同时拥有getter和setter⽅法。
  2. ⽤private修饰的属性编译器将会省略getter和setter⽅法,因为在类外部已经⽆法访问它了,这两个⽅法的存在也就没有意义了。

内部类解决多继承问题

class OuterKotlin{
    val name = "This is not Kotlin's inner class syntax"
    class ErrorInnerKotlin{ // 这是嵌套类
        fun printName(){ 
            println("this name is $name")  //Unresolved reference: name
        }
    }
}
/*
当前我们声明的并不是Kotlin中的内部类,⽽是嵌套类的语法。
如果要在Kotlin 中声明⼀个内部类,我们必须在这个类前⾯加⼀个inner关键字,就像这样⼦:*/
class OuterKotlin{
    val name = "This is not Kotlin's inner class syntax"
    inner class InnerKotlin{ // 这是嵌套类
        fun printName(){
            println("this name is $name")
        }
    }
}
内部类和嵌套类
/*
* Kotlin是相反的思路,默认是⼀个嵌套类,必须加上inner关键字才是⼀个内部类,
* 也就是说可以把静态的内部类看成嵌套类。
* 内部类和嵌套类有明显的差别,具体体现在:内部类包含着对其外部类实例的引⽤,在内部类中我们可以使⽤外部类中的属性,
* ⽐如上⾯例⼦中的name属性;⽽嵌套类不包含对其外部类实例的引⽤,所以它⽆法调⽤其外部类的属性。*/
/*我们使用下面的例子来实现内部类实现多继承,主要是马和驴子生下了驴子*/
open class Horse{ //妈
    fun runFast(){
        println("I can run fast")
    }
}
open class Donkey{ // 驴子
    fun doLongTimeThing(){
        println("I can do some thing long time")
    }
}
class Mule{ // 骡子
    fun runFast(){
        HorseC().runFast()
    }
    fun doLongTimeThing(){
        DonkeyC().doLongTimeThing()
    }
    private inner class HorseC:Horse()
    private inner class DonkeyC:Donkey()
}
/*
1、我们可以在⼀个类内部定义多个内部类,每个内部类的实例都有⾃⼰的独⽴状态,它们与外部对象的信息相互独⽴;
2、通过让内部类HorseC、DonkeyC分别继承Horse和Donkey这两个外部类,我们就可以在Mule类中定义它们的实例对象,
从⽽获得了Horse和Donkey两者不同的状态和⾏为;
3.我们可以利⽤private修饰内部类,使得其他类都不能访问内部类,具有⾮常良好的封装性。*/

使⽤委托代替多继承

/*简单来说,委托是⼀种特殊的类型,⽤于⽅法事件委托,
⽐如你调⽤A类的methodA⽅法,其实背后是B类的methodA去执⾏。
 我们只需通过by关键字就可以实现委托的效果。⽐如我们之前提过的by lazy语法,
 其实就是利⽤委托实现的延迟初始化语法。*/
interface CanFly{
    fun fly()
}
interface CanEat{
    fun eat()
}
open class Flyer1 : CanFly{
    override fun fly() {
        println("I can fly")
    }
}
open class Animal1 : CanEat{
    override fun eat() {
        println("I can eat")
    }
}
class Bird1(fly:Flyer1,animal: Animal1):CanFly by fly,CanEat by animal{}
fun main(){
    val fly = Flyer1()
    val animal = Animal1()
    val b = Bird1(fly,animal)
    b.fly()
    b.eat()
}
/*
* 1、前⾯说到接⼜是⽆状态的,所以即使它提供了默认⽅法实现也是很简单的,不能实现复杂的逻辑,
* 也不推荐在接⼜中实现复杂的⽅法逻辑。我们可以利⽤上⾯委托的这种⽅式,虽然它也是接⼜委托,
* 但它是⽤⼀个具体的类去实现⽅法逻辑,可以拥有更强⼤的能⼒。
* 2、假设我们需要继承的类是A,委托对象是B、C、我们在具体调⽤的时候并不是像组合⼀样A.B.method,
* ⽽是可以直接调⽤A.method,这更能表达A拥有该method的能⼒,
* 更加直观,虽然背后也是通过委托对象来执⾏具体的⽅法逻辑的。*/

数据类

// 定义数据类
data class Bird2(var weight:Double, var age:Int, var color: String)
// 编译成Java代码
public final class Bird2 {
   private double weight;
   private int age;
   @NotNull
   private String color;

   public final double getWeight() {
      return this.weight;
   }

   public final void setWeight(double var1) {
      this.weight = var1;
   }

   public final int getAge() {
      return this.age;
   }

   public final void setAge(int var1) {
      this.age = var1;
   }

   @NotNull
   public final String getColor() {
      return this.color;
   }

   public final void setColor(@NotNull String var1) {
      Intrinsics.checkNotNullParameter(var1, "<set-?>");
      this.color = var1;
   }

   public Bird2(double weight, int age, @NotNull String color) {
      Intrinsics.checkNotNullParameter(color, "color");
      super();
      this.weight = weight;
      this.age = age;
      this.color = color;
   }

   public final double component1() {
      return this.weight;
   }

   public final int component2() {
      return this.age;
   }

   @NotNull
   public final String component3() {
      return this.color;
   }

   @NotNull
   public final Bird2 copy(double weight, int age, @NotNull String color) {
      Intrinsics.checkNotNullParameter(color, "color");
      return new Bird2(weight, age, color);
       /*
       的copy⽅法的主要作⽤就是帮我们从已有的数据类对象中拷贝⼀个新的数据类对象。
       在copy的执⾏过程中,若你未指定具体属性的值,
	   那么新⽣成的对象的属性值将使⽤被copy对象的属性值,
	   这便是我们平常所说的浅拷贝*/
   }

   // $FF: synthetic method
   public static Bird2 copy$default(Bird2 var0, double var1, int var3, String var4, int var5, Object var6) {
      if ((var5 & 1) != 0) {
         var1 = var0.weight;
      }

      if ((var5 & 2) != 0) {
         var3 = var0.age;
      }

      if ((var5 & 4) != 0) {
         var4 = var0.color;
      }

      return var0.copy(var1, var3, var4);
   }

   @NotNull
   public String toString() {
      return "Bird2(weight=" + this.weight + ", age=" + this.age + ", color=" + this.color + ")";
   }

   public int hashCode() {
      int var10000 = (Double.hashCode(this.weight) * 31 + Integer.hashCode(this.age)) * 31;
      String var10001 = this.color;
      return var10000 + (var10001 != null ? var10001.hashCode() : 0);
   }

   public boolean equals(@Nullable Object var1) {
      if (this != var1) {
         if (var1 instanceof Bird2) {
            Bird2 var2 = (Bird2)var1;
            if (Double.compare(this.weight, var2.weight) == 0 && this.age == var2.age && Intrinsics.areEqual(this.color, var2.color)) {
               return true;
            }
         }

         return false;
      } else {
         return true;
      }
   }
}

/*这段代码是不是和JavaBean代码很相似,同样有getter/setter、
equals、hashcode、构造函数等⽅法,其中的equals和hashcode使得
⼀个数据类对象可以像普通类型的实例⼀样进⾏判等*/

关于componentN()方法解释

image.png
image.png
image.png

Pair和Triple

// 看看他们的源码
//Pair
public data class Pair<out A, out B>(
public val first: A,
public val second: B)
//Triple
public data class Triple<out A, out B, out C>(
public val first: A,
public val second: B,
public val third: C)

// 关于使用
    val pair = Pair(20.0, 1)
    val triple = Triple(20.0, 1, "blue")
//利⽤属性顺序获取值
    val weightP = pair.first
    val ageP = pair.second
    val weightT = triple.first
    val ageT = triple.second
    val colorT = triple.third
//当然我们也可以利⽤解构
    val (weightP, ageP) = Pair(20.0, 1)
    val (weightT, ageT, colorT) = Triple(20.0, 1, "blue")

数据类的约定与使⽤

如果你要在Kotlin声明⼀个数据类,必须满⾜以下⼏点条件:
·数据类必须拥有⼀个构造⽅法,该⽅法⾄少包含⼀个参数,⼀个没有数据的数据类是没有任何⽤处的;
·与普通的类不同,数据类构造⽅法的参数强制使⽤var或者val进⾏声明;
·data class之前不能⽤abstract、open、sealed或者inner进⾏修饰;
·在Kotlin1.1版本前数据类只允许实现接⼜,之后的版本既可以实现接⼜也可以继承类。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Kotlin核心编程(七) 的相关文章

  • 将非 Android 项目添加到 Android 项目

    我在 Eclipse 中有三个项目 Base Server 和 AndroidClient Base和Server是Java 1 7项目 而AndroidClient显然是一个android项目 基础项目具有在服务器和 Android 客户
  • 如何在字段值无效的情况下更改 Struts2 验证错误消息?

    我在 Web 表单上使用 Struts2 验证 如果字段假设为整数或日期 则
  • Android:canvas.drawBitmap() 方法无法正常工作

    我已经发布了两个与此相关的问题 请参考此自定义饼图 1 https stackoverflow com questions 28343600 customize pie chart in quarter shape at the botto
  • 将人类日期(当地时间 GMT)转​​换为日期

    我正在服务器上工作 服务器正在向我发送 GMT 本地日期的日期 例如Fri Jun 22 09 29 29 NPT 2018在字符串格式上 我将其转换为日期 如下所示 SimpleDateFormat simpleDateFormat ne
  • 在 Xamarin 中隐藏软键盘

    如何隐藏软键盘以便在聚焦时显示Entry在 Xamarin forms 便携式表单项目中 我假设我们必须为此编写特定于平台的渲染器 但以下内容不起作用 我创建自己的条目子类 public class MyExtendedEntry Entr
  • Jetty、websocket、java.lang.RuntimeException:无法加载平台配置器

    我尝试在 Endpoint 中获取 http 会话 我遵循了这个建议https stackoverflow com a 17994303 https stackoverflow com a 17994303 这就是我这样做的原因 publi
  • Android 为什么这不会抛出错误的线程异常?

    我的印象是视图只能从主线程操作 但是 为什么这不会崩溃 public class MainActivity extends Activity TextView tv Override protected void onCreate Bund
  • 使用 Elastic Beanstalk 进行 Logback

    我在使用 Elastic Beanstalk 记录应用程序日志时遇到问题 我正在 AWS Elastic Beanstalk 上的 Tomcat 8 5 with Corretto 11 running on 64bit Amazon Li
  • JDBC 时间戳和日期 GMT 问题

    我有一个 JDBC 日期列 如果我使用 getDate 则会得到 date 仅部分2009 年 10 月 2 日但如果我使用 getTimestamp 我会得到完整的 date 2009 年 10 月 2 日 13 56 78 890 这正
  • 轻松的反应

    我有一个与这里描述的类似的案例 动态更改RESTEasy服务返回类型 https stackoverflow com questions 3786781 dynamically change resteasy service return
  • Java Swing - 如何禁用 JPanel?

    我有一些JComponents on a JPanel我想在按下 开始 按钮时禁用所有这些组件 目前 我通过以下方式显式禁用所有组件 component1 setEnabled false 但是有什么办法可以一次性禁用所有组件吗 我尝试禁用
  • 为什么\0在java中不同系统中打印不同的输出

    下面的代码在不同的系统中打印不同的输出 String s hello vsrd replace 0 System out println s 当我在我的系统中尝试时 Linux Ubuntu Netbeans 7 1 它打印 When I
  • 找不到数据库路径是不可能的

    我对 android 开发很陌生 现在我正在尝试通过扩展 SQLiteOpenHelper 的类创建数据库 我确信数据存储在我的 Nexus 7 我用来测试应用程序的设备 上的某个位置 但是我找不到数据库的路径 我四处寻找其他类似的问题 所
  • React Native HTTPS Api 调用在 IOS 中有效,但在 Android 中无效

    所以基本上我所做的就是简单地对启用了 HTTPS 的 UAT 服务器进行简单的 Axios 调用 我已经在 IOS 中测试了整个应用程序 API 调用工作正常 但一旦我在 Android 中测试了相同的应用程序 在真正的 Android 设
  • 使用 HtmlUnit 定位弹出窗口

    我正在构建一个登录网站并抓取一些数据的程序 登录表单是一个弹出窗口 所以我需要访问这个www betexplorer com网站 在页面的右上角有一个登录链接 写着 登录 我单击该链接 然后出现登录弹出表单 我能够找到顶部的登录链接 但找不
  • 如何解决 greenDAO 在执行 InsertOrReplace 时“不存在这样的表错误”?

    我正在使用 greenDAO 并且已成功生成所有必需的类和实体 并且我可以看到我的表已创建 但是在要替换的行上放置断点后 我收到一条错误消息 告诉我 不存在这样的表错误 try appTimeUsageDao insertOrReplace
  • Log4j2 ThreadContext 映射不适用于parallelStream()

    我有以下示例代码 public class Test static System setProperty isThreadContextMapInheritable true private static final Logger LOGG
  • 在线性布局内的 ScrollView 内并排对齐 TextView

    我有一个带有滚动视图的线性布局 我想保留它的当前格式 但只需将 textView2a 和 textView3a 并排放置 而不会破坏我当前的布局格式 我已经包含了我最近的尝试 但它们似乎不正确 提前致谢 Java菜鸟 当前有效的 XML
  • View.post(),以及当Runnables被执行时

    我最初的问题是需要知道我的根的高度和宽度View这样我就可以进行程序化的布局更改 就我的目的而言 我不一定需要在onCreate 对于我来说 以编程方式添加我的孩子就足够了View根布局完成后 因此我很乐意使用onWindowFocusCh
  • java'assert'和'if(){}else exit;'之间的区别

    java和java有什么区别assert and if else exit 我可以用吗if else exit代替assert 也许有点谷歌 您应该记住的主要事情是 if else 语句应该用于程序流程控制 而assert 关键字应该仅用于

随机推荐

  • S-DES加密

    S DES加密 Simplified Data Encryption Standard S DES 是一个供教学的非安全的加密算法 它与DES的特性和结构类似 但参数小 明文分组为8位 主密钥分组为10位 采用两轮迭代 S DES加密过程包
  • 第十一讲、FPGA开发中xilinx vivado 平台时序分析系列课程-边沿对齐input delay ddr双沿采样时序约束与收敛

    我们在使用一些以太网PHY和FPGA接口是RGMII接口是DDR双沿结构 还有ADC芯片也也是DDR双沿采样接口 以及CMOS视频传感器也有很多DDR双沿源同步接口 我们这里以IMX222视频传感器的的DDR为例约束input ddr 接口
  • FPGA提示产生latch的报错

    在fpga的设计中有时会遇到 latch 的报错 1 latch是什么 Latch 就是锁存器 是一种在异步电路系统中 对输入信号电平敏感的单元 用来存储信息 锁存器在数据锁存使能时 数据被锁存 输入信号不起作用 这违背了组合逻辑中输出随输
  • selenium元素定位方法 id,name,class

    1 导入selenium from selenium import webdriver from time import sleep 2 打开浏览器 最大化 driver webdriver Chrome driver maximize w
  • Java 学习路线大全,再也不用迷路啦(持续更新)

    路线特点 最新 完整一条龙 从入门到入土 表示推荐学习 给出目标 学习建议 关键知识点 最优资源以及各类资源推荐 视频 书籍 文档 项目 工具等 划分阶段 更有计划 且在最后给出持续学习的方向 探索 Java 程序员发展的无限可能 前言 首
  • SQLSERVER排查CPU占用高的情况

    一般排查都是用下面的脚本 一般会用到三个视图 sys sysprocesses dm exec sessions dm exec requests sys sysprocesses 系统表是一个很重要的系统视图 主要用来定位与解决Sql S
  • 存储类型auto,static,extern,register的区别 <转>

    变量和函数的属性包括数据类型和数据的存储类别 存储类别指数据在内存中存储方式 静态和动态 包含auto static register extern四种 内存中 具体点来说内存分为三块 静态区 堆区 栈区 外部变量和全局变量存放在静态区 局
  • 半监督学习——数据精馏(论文阅读)

    论文地址 https arxiv org pdf 1712 04440 pdf 1 论文与摘要 Data Distillation Towards Omni Supervised Learning 摘要 作者提出一种特殊的半监督学习方法 取
  • android 最新动态,浅谈Android动态页面(一)

    这是一个很微妙的东西 可能平时经常用到 但是没注意 我想对这个内容进行一个总结并提出一些看法 谈的是动态页面 不是动态布局 一 什么是动态页面 什么是动态页面 我认为是一种在开发时的设计思想 最终展示的页面会随着数据的改变而改变 或者说会根
  • OpenCV中如何读取URL图像文件

    点击上方 小白学视觉 选择加 星标 或 置顶 重磅干货 第一时间送达 由来 最近知识星球收到的提问 觉得是一个很有趣的问题 就通过搜集整理归纳了一番 主要思想是通过URL解析来生成数据 转为图像 Mat对象 但是在Python语言与C 语言
  • Java基础学习总结(1)——equals方法

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 一 equals方法介绍 1 1 通过下面的例子掌握equals的用法 1 package cn galc test 2 3 public class TestEquals
  • 简单spring cloud服务升级实现

    1 升级原则 隔离性 v1升级到v2时 相互独立 互不不干扰 稳定性 服务不停止 完成升级 接口保持畅通 2 具体实现 2 1 eureka项目 搭建eureka 网上很多 就省略了 2 2 feign接口项目 2 2 1 依赖
  • React Hooks

    React Hooks 为什么使用 React Hook useState hook useReducer hook useEffect hook useRef hook useLayoutEffect hook useImperative
  • GPIO口的八种工作状态

    一直对GPIO的工作状态不是很熟悉 导致在设置IO状态时 经常会设置成推挽上拉 或者推挽下拉 开漏上拉等问题 虽然看起来没有影响MCU工作 但感觉这是一种无知的表现 现在总结下GPIO口的八种工作状态 其中四种输入状态 四种输出状态 一 输
  • (STM32笔记2)基于hc05的蓝牙实验

    实验任务 开机检测 HC05 蓝牙模块是否存在 如果检测不成功 则报错 检测成功之后 显示模块的主从状态 并显示模块是否处于连接状态 DS0 闪烁 提示程序运行正常 按 KEY0 按键 可以开启 关闭自动发送数据 通过蓝牙模块发送 按 KE
  • 简单工厂模式

    简单工厂模式 一 概念 从设计模式的类型上来说 简单工厂模式是属于创建型模式 又叫做静态工厂方法 StaticFactory Method 模式 但不属于23种GOF设计模式之一 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例 简
  • ASIC中带有MUX的时钟路径时序约束

    链接 https pan baidu com s 1BrAsabLYLGbvdXJB2LQwiA 提取码 mgrn
  • 回溯法详解

    一 回溯法 深度优先搜素 1 简单概述 回溯法思路的简单描述是 把问题的解空间转化成了图或者树的结构表示 然后使用深度优先搜索策略进行遍历 遍历的过程中记录和寻找所有可行解或者最优解 基本思想类同于 图的深度优先搜索 二叉树的后序遍历 分支
  • 旋转变换(一)旋转矩阵

    转自 https blog csdn net csxiaoshui article details 65446125 1 简介 计算机图形学中的应用非常广泛的变换是一种称为仿射变换的特殊变换 在仿射变换中的基本变换包括平移 旋转 缩放 剪切
  • Kotlin核心编程(七)

    Kotlin核心编程 七 文章目录 Kotlin核心编程 七 多继承问题 接口实现多继承问题 getter和setter 内部类解决多继承问题 内部类和嵌套类 使 委托代替多继承 数据类 Pair和Triple 数据类的约定与使 多继承问题