我想在Kotlin中为具有不可变属性的类型使用类型安全生成器。
class DataClass(val p1:String, val p2:String) {}
fun builder(buildBlock: DataClass.() -> Unit) {
return DataClass(p1 = "",p2 = "").also(block)
}
//...
builder {
p1 = "p1" // <-- This won't compile, since p1 is a val
p2 = "p2" // <-- This won't compile, since p2 is a val
}
我想到了两种解决方案:
选项 1:创建生成器类:
class DataClass(val p1: String, val p2: String) {}
class DataClassBuilder(){
lateinit var p1: String
lateinit var p2: String
fun build() = DataClass(p1, p2)
}
fun builder(buildBlock: DataClassBuilder.() -> Unit) {
return DataClassBuilder().also(block).build()
}
选项2:创建自定义委托以防止再次设置该值:
class InitOnceDelegate: ReadWriteProperty<DTest, String> {
private var state: String? = null
override fun getValue(thisRef: DTest, property: KProperty<*>): String {
return state ?: throw IllegalStateException()
}
override fun setValue(thisRef: DTest, property: KProperty<*>, value: String) {
if (state == null) {
state = value
} else {
throw IllegalStateException("${property.name} has already been initialized")
}
}
}
class DataClass() {
var p1: String by InitOnceDelegate()
var p2: String by InitOnceDelegate()
}
fun builder(buildBlock: DataClass.() -> Unit) {
return DataClass(p1 = "",p2 = "").also(block)
}
//...
val d = builder {
p1 = "p1"
p2 = "p2"
}
d.p1 = "another value" // <-- This will throw an exception now.
选项1的缺点是我必须维护两个类,选项2的缺点是编译器将允许再次设置< code>DataClass中的值,并且检查将只在运行时进行。
有没有更好的方法来解决这个问题而没有提到的缺点?
这是一种不成熟的解决方案,仍然需要您维护两个类:
interface DataClass
{
companion object
{
fun builder(callback : DataClassImpl.() -> Unit) : DataClass
= DataClassImpl().apply { callback() }
}
val p1 : String
val p2 : String
}
class DataClassImpl : DataClass
{
override lateinit var p1 : String
override lateinit var p2 : String
}
与选项1不同,在本例中只创建一个实例,与选项2不同,编译器将告诉您是否尝试在生成器
块后更改p1
、或p2
的值。
为了避免将结果强制转换为< code>DataClassImpl并在事后更改值,可以像这样委托接口:
interface DataClass
{
companion object
{
fun builder(callback : DataClassBuilder.() -> Unit) : DataClass
= DataClassBuilder().apply { callback() }.let { DataClassImpl(it) }
}
val p1 : String
val p2 : String
}
class DataClassBuilder : DataClass
{
override lateinit var p1 : String
override lateinit var p2 : String
}
class DataClassImpl(
private val delegate : DataClass
) : DataClass by delegate
本文向大家介绍Python的可变类型和不可变类型?相关面试题,主要包含被问及Python的可变类型和不可变类型?时的应答技巧和注意事项,需要的朋友参考一下 可变数据类型:列表、字典、可变集合 不可变数据类型:数字、字符串、元组、不可变集合
问题内容: 我对什么是不可变类型感到困惑。我知道该float对象被认为是不可变的,在我的书中有这样的例子: 由于类的结构/层次结构,这是否被认为是不可变的?意思float是在类的顶部,是它自己的方法调用。类似于此类示例(即使我的书说的dict是可变的): 可变的东西在类内部具有方法,例如以下类型: 另外,对于最后一个,如果我将这种类型的set传递给它: 不调用该example方法,它返回一个字典。
问题内容: 我有课 和班级 关键是该方法不安全,因为我可以提供的项目与当前报告无关,但与其他报告相关,编译器不会抱怨。 是否可以用类型安全的方式编写该方法,即我们可以仅将T作为当前报表的类型作为参数传递。 问题答案: 我认为您正在寻找以下内容。 它的工作方式是: 您想用从 您要确保所有列表都属于同一类型 为了将参数绑定到从扩展的对象,您需要对自身进行参数化: 您添加需要从报表扩展的绑定 但是您要
将Android Studio升级到4.0版本后,在“gradle-wrapper.properties”中:
大部分现代语言使用某些方法去解决了这个问题,Kotlin的方法跟别的相似的语言比是相当另类和不同的。但是黄金准则还是一样:如果变量是可以是null,编译器强制我们去用某种方式去处理。 指定一个变量是可null是通过在类型的最后增加一个问号。因为在Kotlin中一切都是对象(甚至是Java中原始数据类型),一切都是可null的。所以,当然我们可以有一个可null的integer: val a: In
我有一个静态编程语言数据类,我正在用许多不可变属性构建它,这些属性是从单独的SQL查询中获取的。如果我想使用构建器模式构建数据类,如何在不使这些属性可变的情况下做到这一点? 例如,而不是通过构造 我想用 同时仍然使用Kotlin的数据类特性和不可变属性。