提问人:Robbie 提问时间:2/9/2023 更新时间:2/10/2023 访问量:54
为什么我必须将自定义适配器对象强制转换为类?
Why Do I Have to Cast My Custom Adapter Object to a Class?
问:
我正在使用 Kotlin 开发一个简单的 Android 应用程序,目前正在实现 .我的类 , 与我在 .我把它附在我的喜欢中:android.widget.BaseAdapter
GridAdapter
GridView
activity_main.xml
MainActivity.kt
val gridView = findViewById<GridView>(R.id.gridView)
gridView.adapter = GridAdapter(applicationContext)
我不明白的是,每当我想调用该适配器的函数之一时,我必须首先将其(对象)转换为类,如下所示:GridAdapter
GridAdapter
(gridView.adapter as GridAdapter).addImage(imageView)
尽管事实未声明为静态,但这是事实。下面是方法签名:addImage
fun addImage(image: ImageView)
在我看来,这似乎是一个荒谬的陈述,在任何其他情况下都会立即导致编译错误,但 Android Studio linter 却对此发誓。为什么?这是怎么回事?
答:
GridView
的适配器是(继承自 ):ListAdapter
AbsListView
ListAdapter mAdapter;
每当你访问时,你都会从编译器的角度得到一个不是你的。由于您知道它始终是运行时的,因此您可以将其强制转换而不会冒 .gridView.adapter
ListAdapter
GridAdapter
GridAdapter
ClassCastException
addImage
似乎是一个函数,因此需要强制转换来调用该函数。 根本没有那个功能。GridAdapter
ListAdapter
与其每次都进行强制转换,不如保留对你的引用并使用该引用呢?喜欢GridAdapter
val adapter = GridAdapter(applicationContext)
gridView.adapter = adapter
adapter.addImage(imageView)
的签名 has it 返回一个泛型,因为您可以将其设置为 的任何子类型,因为 OOP 的 Liskov 替换原理。GridAdapter.adapter
Adapter
Adapter
它返回给您的实际适配器是 GridAdapter,因为这是您之前传递给它的子类型。但编译器并不知道这一点。编译器无法确定在此特定情况下,返回的 Adapter 是专门的 GridAdapter。适配器可能已在另一个函数中或由另一个线程等更改为其他类型。编译器永远不可能复杂到足以弄清楚这样的事情,因为它无法在每次键入一行代码时都运行应用程序的整个模拟,因此它可以分析和找出所有的可能性。
所以你强制转换它来告诉编译器,它实际上是一个 .请记住,强制转换实际上并未执行任何转换。这只是你对编译器做出的承诺,即你正在使用的变量已经是你声称的类型。Adapter
GridAdapter
我不确定你为什么提到这个函数不是静态的。这与选角无关。
评论