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



我是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.

它与构造函数有何不同?

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

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

您可以在文档中阅读一些关于泛型的内容,但文档更关注与Java的差异(例如关于泛型差异(,而不是解释泛型的基本知识。@Tenfour04提到的Java文档更有指导意义。

基本上,当类的代码除了类的某些输入/输出值的类型(构造函数/方法参数和返回类型(之外应该是相同的时,泛型类是有用的。它允许有更多的类型安全性,而不仅仅是在任何地方使用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<T>类,其中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<T>可以与任何类型的T一起使用,但有时您希望将该类型约束为只接受某些类型。这就是:的语法来源:

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的子类型。

相关内容

  • 没有找到相关文章

最新更新