我刚刚开始使用并开始弄乱抽象类,覆盖val和singeltons.但是,我刚刚遇到了一个非常奇怪的行为.我的目标是要有一个抽象类,然后创建几个扩展该抽象类的singelton.由于我需要某些变量,因此我创建了抽象val,然后可以在子类中对其进行覆盖(而不是通过构造函数传递它们).
所以我有4节课:
主要活动:
class MainActivity : AppCompatActivity() { overrIDe fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentVIEw(R.layout.activity_main) val instance = Instance() Log.d("MainActivity", "instance randobject: ${instance.randobject}") Log.d("MainActivity", "instance randobject: ${instance.randobject.myProp}") Log.d("MainActivity", "instance randobject: ${instance.randobject.myProp2}") Log.d("MainActivity", "singleton randobject: ${Object.randobject}") Log.d("MainActivity", "singleton randobject: ${Object.randobject.myProp}") Log.d("MainActivity", "singleton randobject: ${Object.randobject.myProp2}") }}
实例:
class Instance: AClass(){ overrIDe val testString: String = "test" overrIDe val testUriString: String = "https://www.Google.se" overrIDe val testUri: Uri = Uri.parse(testUriString)!! overrIDe val randobject: RandomObject = RandomObject("Herp")}
宾语
object Object : AClass(){ overrIDe val testString: String = "test" overrIDe val testUriString: String = "https://www.Google.se" overrIDe val testUri: Uri = Uri.parse(testUriString)!! overrIDe val randobject: RandomObject = RandomObject("Herp")}
一类:
abstract class AClass{ abstract val testString: String abstract val testUriString: String abstract val testUri: Uri abstract val randobject: RandomObject init { Log.d("AClass", "testString: $testString") Log.d("AClass", "testUriString: $testUriString") Log.d("AClass", "testUri: $testUri") Log.d("AClass", "randobject: $randobject") }}
输出:
D/AClass: testString: nullD/AClass: testUriString: nullD/AClass: testUri: nullD/AClass: randobject: nullD/MainActivity: instance randobject: com.technocreatives.abstracttest.RandomObject@4455b26D/MainActivity: instance randobject: derpD/MainActivity: instance randobject: HerpD/AClass: testString: testD/AClass: testUriString: https://www.Google.seD/AClass: testUri: nullD/AClass: randobject: nullD/MainActivity: singleton randobject: com.technocreatives.abstracttest.RandomObject@8b19367D/MainActivity: singleton randobject: derpD/MainActivity: singleton randobject: Herp
在此之后,我意识到,只有在执行了init {}之后,覆盖的对象才会被初始化.但是后来我看到当我创建一个单例时发生了什么.值testUriString在init中设置.为什么会这样呢?是虫子吗?单例和覆盖val的预期行为是什么?
我尝试搜索文档,但是在文档中找不到与此有关的任何信息.
解决方法:
您观察到的行为上的差异是由于如何为类和对象中的属性生成后备字段以及初始化它们的方式引起的.
>当一个类使用背景字段来覆盖属性时,在幕后,派生类中将有一个单独的实例字段,并且被覆盖的getter返回该字段的值.
因此,当您从超类构造函数内部访问属性时,将调用被覆盖的getter,该方法将返回字段的null值(此时未初始化,因为超级构造函数是在类自己的初始化之前被调用的逻辑).
>相反,当您定义覆盖类的对象时,基础类Object的后备字段定义为JVM静态字段.
Object类也有一个实例(甚至可以在Java中以Object.INSTANCE的形式进行访问),并且该实例在某个时间点被初始化并调用超级构造函数.
现在有趣的部分:当由JVM加载对象类时,由常量值初始化的静态字段已经包含了这些值,甚至在对象的< clinit>中的PUTSTATIC指令之前也是如此.被执行.
如果将testString初始值设定项更改为非恒定值,则在访问它时将不会对其进行初始化,例如覆盖val testString:String =“ test”.也{println(it)}
Here’s a gist带有这样一个单例的字节码,我自己做了一些标记.
注意,在将值放入< clinit>之前,抽象类的构造函数会访问该字段.对象.
我不确定这实际上是一个错误,但至少行为是不一致的.我已将此问题报告给问题跟踪工具:https://youtrack.jetbrains.com/issue/KT-21764
总结以上是内存溢出为你收集整理的android-Kotlin覆盖抽象val行为,对象与类全部内容,希望文章能够帮你解决android-Kotlin覆盖抽象val行为,对象与类所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)