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核心编程(七) 的相关文章

  • Mockito when().thenReturn 不必要地调用该方法

    我正在研究继承的代码 我编写了一个应该捕获 NullPointerException 的测试 因为它试图从 null 对象调用方法 Test expected NullPointerException class public void c
  • Ubuntu 16.04 - Genymotion:找不到 /dev/hw_random

    I install Genymotion on the Ubuntu 16 04 64Bit I created a virtual emulator for Android 6 0 then I run this emulator but
  • 禁止的软件包名称:java

    我尝试从数据库名称为 jaane 用户名 Hello 和密码 hello 获取数据 错误 java lang SecurityException Prohibited package name java at java lang Class
  • 尝试在 ubuntu 中编译 android 内核时出错

    我正在尝试从源代码编译 Android 内核 并且我已经下载了所有正确的软件包来执行此操作 但由于某种原因我收到此错误 arm linux androideabi gcc error unrecognized command line op
  • Android Studio 0.4.3 Eclipse项目没有gradle

    在此版本之前 在 Android Studio 中按原样打开 Eclipse 项目似乎很容易 无需任何转换 我更喜欢 Android Studio 环境 但我正在开发一个使用 eclipse 作为主要 IDE 的项目 我不想只为这个项目下载
  • 科特林;按多个字段分组

    如何在代码中按三个或更多字段进行 groupBy 我的代码如下 val nozzleSaleReport nozzleStateList groupBy it shift id it createUser id it nozzle id H
  • getResourceAsStream() 可以找到 jar 文件之外的文件吗?

    我正在开发一个应用程序 该应用程序使用一个加载配置文件的库 InputStream in getClass getResourceAsStream resource 然后我的应用程序打包在一个 jar文件 如果resource是在里面 ja
  • 在 Mac 上正确运行基于 SWT 的跨平台 jar

    我一直致力于一个基于 SWT 的项目 该项目旨在部署为 Java Web Start 从而可以在多个平台上使用 到目前为止 我已经成功解决了由于 SWT 依赖的系统特定库而出现的导出问题 请参阅相关thread https stackove
  • 无法捆绑适用于 Mac 的 Java 应用程序 1.8

    我正在尝试将我的 Java 应用程序导出到 Mac 该应用程序基于编译器合规级别 1 7 我尝试了不同的方法来捆绑应用程序 1 日食 我可以用来在 Eclipse 上导出的最新 JVM 版本是 1 6 2 马文 看来Maven上也存在同样的
  • 如何从终端运行处理应用程序

    我目前正在使用加工 http processing org对于一个小项目 但是我不喜欢它附带的文本编辑器 我使用 vim 编写所有代码 我找到了 pde 文件的位置 并且我一直在从 vim 中编辑它们 然后重新打开它们并运行它们 重新加载脚
  • 如何从指定日期获取上周五的日期? [复制]

    这个问题在这里已经有答案了 如何找出上一个 上一个 星期五 或指定日期的任何其他日期的日期 public getDateOnDay Date date String dayName 我不会给出答案 先自己尝试一下 但是 也许这些提示可以帮助
  • 如何在桌面浏览器上使用 webdriver 移动网络

    我正在使用 selenium webdriver 进行 AUT 被测应用程序 的功能测试自动化 AUT 是响应式网络 我几乎完成了桌面浏览器的不同测试用例 现在 相同的测试用例也适用于移动浏览器 因为可以从移动浏览器访问 AUT 由于它是响
  • 声明的包“”与预期的包不匹配

    我可以编译并运行我的代码 但 VSCode 中始终显示错误 早些时候有一个弹出窗口 我不记得是什么了 我点击了 全局应用 从那以后一直是这样 Output is there but so is the error The declared
  • simpleframework,将空元素反序列化为空字符串而不是 null

    我使用简单框架 http simple sourceforge net http simple sourceforge net 在一个项目中满足我的序列化 反序列化需求 但在处理空 空字符串值时它不能按预期工作 好吧 至少不是我所期望的 如
  • Android:膨胀布局时出现 StackOverFlowError 和 InvokingTargetException

    首先 对不起我的英语 我在膨胀布局时有一个问题 我有一个自定义视图 从 LinearLayout 扩展而来 称为按钮帮助 我在名为的布局上使用该视图加载活动 我的以下代码在所有设备和模拟器上都能完美运行 但具有 QVGA 屏幕 例如 Sam
  • 静态变量的线程安全

    class ABC implements Runnable private static int a private static int b public void run 我有一个如上所述的 Java 类 我有这个类的多个线程 在里面r
  • 当我从 Netbeans 创建 Derby 数据库时,它存储在哪里?

    当我从 netbeans 创建 Derby 数据库时 它存储在哪里 如何将它与项目的其余部分合并到一个文件夹中 右键单击Databases gt JavaDB in the Service查看并选择Properties This will
  • 按日期对 RecyclerView 进行排序

    我正在尝试按日期对 RecyclerView 进行排序 但我尝试了太多的事情 我不知道现在该尝试什么 问题就出在这条线上适配器 notifyDataSetChanged 因为如果我不放 不会显示错误 但也不会更新 recyclerview
  • Spring Boot @ConfigurationProperties 不从环境中检索属性

    我正在使用 Spring Boot 1 2 1 并尝试创建一个 ConfigurationProperties带有验证的bean 如下所示 package com sampleapp import java net URL import j
  • 强制 Listview 不重复使用视图(复选框)

    我做了一个定制Listview 没有覆盖getView 方法 Listview 中的每个项目都具有以下布局 联系布局 xml

随机推荐

  • 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 数据类的约定与使 多继承问题