抽象类 BaseVMActivity<VM : ViewModel, B : ViewBinding> 和抽象类 BaseVMActivity(VM : ViewModel, B : Vi

Posted

技术标签:

【中文标题】抽象类 BaseVMActivity<VM : ViewModel, B : ViewBinding> 和抽象类 BaseVMActivity(VM : ViewModel, B : ViewBinding) 的区别【英文标题】:Difference between abstract class BaseVMActivity<VM : ViewModel, B : ViewBinding> and abstract class BaseVMActivity(VM : ViewModel, B : ViewBinding) 【发布时间】:2022-01-18 19:53:08 【问题描述】:

我是 Kotlin 的新手,正在学习它。我想出了一些高级语法。

abstract class BaseVMActivity(VM:ViewModel,B:ViewBinding) => This is I know as constructor.

但是

abstract class BaseVMActivity<VM : ViewModel , B : ViewBinding> => This syntax I didn't understand.

它与构造函数有什么不同?

【问题讨论】:

阅读 Kotlin 文档中的泛型,如果没有意义,请先阅读官方 Java 文档。 【参考方案1】:

&lt;&gt; 的语法用于泛型类型参数,它独立于构造函数。从技术上讲,您可以同时拥有两者:

class BaseVMActivity<VM : ViewModel , B : ViewBinding>(vm: VM, b: B)

您可以阅读一些关于泛型的内容in the documentation,但该文档更侧重于与 Java 的差异(例如关于泛型差异),而不是解释泛型的基础知识。 @Tenfour04 提到的Java documentation 更有指导意义。

基本上,当类的代码除了类的某些输入/输出值的类型(构造函数/方法参数和返回类型)之外应该相同时,泛型类很有用。与在任何地方使用 Any 或其他父类型相比,它可以提供更多的类型安全性。

例如,这个Box 类可以包含任何类型的值:

class Box(var value: Any)

但是当你得到一个 Box 的实例时,你无法在编译时知道它包含什么:访问 box.value 会给你一个类型为 Any 的值,你需要强制转换它(冒着运行时失败的风险) 以获取可用值:

val box: Box = Box("some string")

val value1: String = box.value // not allowed

val value2: String = box.value as String // risky if box is declared somewhere else

val value3: Int = box.value as Int // compiles fine, fails at runtime

泛型是增加编译时安全性的好方法。这是如何声明一个通用的Box&lt;T&gt; 类,其中T 是在实例化该类时确定的类型。 T 被称为Box 类的类型参数Box 的不同实例可以为T 使用不同的类型(它们可以有不同类型的值):

class Box<T>(var value: T)


val box: Box<String> = Box("some string")

// this compiles and is safe, because it's a Box<String>, not any box
val value: String = box.value

val value: Int = box.value // doesn't compile
val value: Int = box.value as Int // doesn't compile, because String can't be cast to Int

现在这个Box&lt;T&gt; 可以与任何类型T 一起使用,但有时您希望constrain that type 只接受某些类型。这就是 : 的语法来源:

abstract class Animal
class Dog : Animal()
class Cat : Animal()

class Box<T : Animal>(val animal: T)

如果我这样声明Box,则只允许Animal 的子类型:

val catBox: Box<Cat> = Box(Cat())
val dogBox: Box<Dog> = Box(Dog())
val stringBox: Box<String> = Box("some string") // doesn't compile

您还可以在泛型类中声明多个类型参数,方法是用逗号分隔它们:

interface Map<K, V>

每个类型参数也可以有自己的界限,这就是你所看到的语法:

abstract class BaseVMActivity<VM : ViewModel , B : ViewBinding>

本例中有VMB两个类型参数,它们必须分别是ViewModelViewBinding的子类型。

【讨论】:

感谢@Joffery,这是简短而清晰的解释。

以上是关于抽象类 BaseVMActivity<VM : ViewModel, B : ViewBinding> 和抽象类 BaseVMActivity(VM : ViewModel, B : Vi的主要内容,如果未能解决你的问题,请参考以下文章

12. 抽象类

Postgre连接类

从具体类派生抽象模板类

C# - 反序列化一个抽象类(指定的类型是抽象的:name='ValueColorConverter', namespace='', at <ValueColorConverter xmlns=

MVVM 简化的Messager类

实现:抽象类和多态的实例