《Kotlin实战》-第07章:运算符重载及其他约定

Kotlin运算符重载及委托属性详解

第七章 运算符重载及其他约定

约定的定义比较模糊,一般说是通过调用自己代码中定义的函数,来实现特定语言结构。
在Kotlin中,这些功能与特定的函数命名相关,而不是与特定的类型绑定。

7.1 重载算术运算符

Kotlin限定了可以重载的运算符,以及需要在类中定义的对应名字的函数。
开发者是不能定义自己的运算符的。

7.1.1 重载二元算术运算

重载运算符:用operator关键字来声明对应函数。本质上就是特定名字的函数罢了。
示例:

//声明
data class Point(val x:Int,val y:Int){
    operator fun plus(other:Point):Point{
        return Point(x + other.x,y + other.y)
    }
}
//调用
val p1 = Point(10,20)
val p2 = Point(30,40)
println(p1 + p2)
>>>>>>>
Point(x=40,y=60)
  • 可重载的二元算术运算符有
    | 表达式 | 函数名 |
    | :— | :----|
    | a*b | times |
    | a/b | div |
    | a%b | mod |
    | a+b | plus |
    | a-b | minus |

其有下面几个要点:
1.可以声明为成员函数或扩展函数。

operator fun Point.plus(other:Point):Point{
    return Point(x + other.x, y + other.y)
}

2.重载的运算符,基本上和与标准数字类型的运算符有着相同的优先级。例如*、/和%的优先级高于+和-。
3.定义运算符的时候,两个运算数的类型是自由的,可以不同的。
4.返回值也是自由的,可以不同于任一运算数类型。
5.和普通函数一样,可以定义多个同名的,但参数类型不同的运算符函数。
6.Koltin运算符没有自动支持交换性,即交换运算符两边运算数是不支持的。因为其对应的是定义时的类型。

位运算

特别的,Kotlin中位运算是没有特殊运算符的。但它使用支持中缀调用语法的常规函数。
Kotlin提供的用于执行位运算的函数列表:

  • shl:带符号左移
  • shr:带符号右移
  • ushr:无符号右移
  • and:按位与
  • or:按位或
  • xor:按位异或
  • inv:按位取反

位运算示例:

println(0x0F and 0xF0)
println(0x0F or 0xF0)
println(0x1 shl 4)
>>>>
0
255
16
7.1.2 重载复合赋值运算符

和二元运算符相似,+=,-=等这些复合赋值运算符也有对应的指定函数,可以被重载。
一般都是对应二元运算符的指定函数再加Assign就是了。如

  • +=:plusAssign
  • -=:minusAssign
  • *=:timesAssign

这里要着重介绍一个问题:这些复合赋值运算符也会调用上节中定义的二元运算符函数。
甚至于,二元运算符函数和复合赋值运算符函数被调用的机会是一样的,而且被要求是唯一的。
例如对于+=,plus和plusAssign都可能被调用。当两者都被定义且适用,编译器会报错。

a += b
//等同于
a = a.plus(b)
//或
a.plusAssign(b)

由此有几点注意:

  • val修饰不可变类型的时候,就不能用plusAssign,除非是集合类或者特别定义了函数内容。
  • 不可变类一般只提供plus就可以,可变类可以只提供plusAssign。

特别地,Kotlin标准库对于集合的关于运算符的支持:

  • +和-:总是返回一个新的集合
  • +=和-=:当是可变集合时,始终在一个地方修改它们;当是只读集合时,会返回一个修改过的副本。但在var修饰只读集合后,也是可以使用的。
  • 运算数可以是单个元素,也可以是集合。

示例:

//声明:Koltlin标准库为可变集合定义了plusAssign函数
operator fun <T> MutableCollection<T>.plusAssign(element:T){
    this.add(element)
}
//调用
val valList = listOf(1,2,3)
var varList = listOf(1,2,3)
val arrayList = arrayListOf(1,2,3)

//valList += 4不允许,会报异常
val newValList = valList + 4
varList += 4
arrayList += 4
     
println(newValList)
println(varList)
println(arrayList)
>>>>>
[1, 2, 3, 4]
[1, 2, 3, 4]
[1, 2, 3, 4]
7.1.3 重载一元运算符

重载一元运算符和上面章节中的方式是相同的,只是对应函数没有参数而已。
可重载的一元运算符对应函数列表:

  • +a:unaryPlus
  • -a:unaryMinus
  • !a:not
  • a++,++a:inc
  • a–,–a:dec

特殊需要注意的是自增自减运算符,涉及的运算优先级是和基本数据类型用到的一样。
示例:

//声明
operator fun BigDecimal.in
安卓报错Duplicate class org.jetbrains.org.objectweb.asm.util.CheckSignatureAdapter$State found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.Printer found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.Textifiable found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.Textifier found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.TraceAnnotationVisitor found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.TraceClassVisitor found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.TraceFieldVisitor found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.TraceModuleVisitor found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10) Duplicate class org.jetbrains.org.objectweb.asm.util.TraceSignatureVisitor found in modules jetified-kotlin-compiler-embeddable-1.4.10 (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.4.10) and jetified-kotlin-gradle-plugin-1.4.10 (org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.10)
04-01
<think>嗯,用户遇到了安卓项目中的重复类错误,涉及多个org.jetbrains.org.objectweb.asm.util下的类。首先,我需要理解这个问题的根本原因。错误信息显示,kotlin-compiler-embeddable和kotlin-gradle-plugin这两个依赖包含了相同的类,导致冲突。这可能是因为这两个库都依赖了不同版本的ASM库,或者它们内部打包了相同类但不同版本。 接下来,我应该考虑常见的解决方法。通常,这类问题可以通过排除重复的依赖来解决。用户需要在构建文件中检查这两个模块的依赖关系,找出哪个模块引入了冲突的ASM类,然后排除掉其中一个。不过,用户提到这两个模块都是来自Kotlin的1.4.10版本,可能这时候需要确认Kotlin插件和Gradle版本是否兼容,或者是否需要升级到更高版本,因为旧版本可能存在已知的依赖冲突问题。 另外,可能需要检查项目中的其他依赖是否间接引入了不同版本的ASM库。使用Gradle的依赖树分析工具(如./gradlew app:dependencies)可以帮助识别冲突的来源。如果发现有多个版本的ASM,可以强制指定使用某个版本,或者排除其他版本。 还有可能是Gradle插件本身的问题,尤其是在使用旧版本的Kotlin插件时。查看官方文档或问题追踪系统,看看是否有相关的问题和解决方案。例如,升级到Kotlin 1.5或更高版本可能已经修复了这个问题,因为JetBrains可能在后续版本中调整了依赖管理。 用户还需要确认项目的Gradle配置是否正确,比如是否在多个地方重复声明了Kotlin插件,或者是否有第三方库强制覆盖了ASM的版本。有时候,插件之间的兼容性问题也会导致此类错误,需要逐一排查。 最后,如果排除依赖或升级版本无效,可能需要更深入分析依赖树,或者寻求社区和官方支持。提供详细的错误日志和构建文件配置会有助于更准确地定位问题。</think>这个错误是由于项目中存在重复的类定义导致的,具体涉及两个Kotlin相关模块中的ASM工具类冲突。以下是逐步分析和解决方案: **根本原因分析** 1. 冲突模块:`kotlin-compiler-embeddable`和`kotlin-gradle-plugin`都包含`org.jetbrains.org.objectweb.asm.util`包下的同名类 2. 典型触发场景:当使用较旧版本的Kotlin插件(如1.4.x)时,其内部依赖的ASM库存在重复打包 **解决方案步骤** 1. **统一Kotlin版本** ```gradle // 在项目根build.gradle中确保所有Kotlin组件版本一致 buildscript { ext.kotlin_version = '1.8.22' // 推荐使用1.7.20+ dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } ``` 2. **排除重复依赖** ```gradle // 在app模块的build.gradle中添加排除规则 configurations { all*.exclude group: 'org.jetbrains.org.objectweb.asm', module: 'asm-util' all*.exclude group: 'org.jetbrains', module: 'kotlin-compiler-embeddable' } ``` 3. **强制使用统一ASM版本** ```gradle // 在项目根build.gradle中添加全局约束 configurations.all { resolutionStrategy { force 'org.ow2.asm:asm:9.4' force 'org.ow2.asm:asm-util:9.4' } } ``` 4. **清理构建缓存** ```bash ./gradlew cleanBuildCache ./gradlew --stop rm -rf $HOME/.gradle/caches/ ``` **验证方法** 1. 查看依赖树: ```bash ./gradlew :app:dependencies --configuration runtimeClasspath ``` 2. 确认输出中不再出现`Duplicate classes`警告 **升级建议** - 若项目允许,建议升级到Kotlin 1.8.x+,该问题在较新版本中已通过优化依赖管理得到解决 - 检查Android Gradle Plugin版本是否与Kotlin版本兼容(参考官方兼容性文档) **技术背景** 该问题源于Kotlin编译器内部使用的ASM库(Java字节码操作框架)在多个子模块中的重复打包。在构建时,Gradle的依赖解析器会发现同一类的多个实例,违反JVM的类唯一性原则。通过依赖排除和版本强制可以确保类加载器只获取单一版本。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值