abstract class BaseVMActivity<VM : ViewModel, B : ViewBinding> 和 abstract class BaseVMActivity(VM : ViewModel, B : ViewBinding) 的区别
Difference between abstract class BaseVMActivity<VM : ViewModel, B : ViewBinding> and abstract class BaseVMActivity(VM : ViewModel, B : ViewBinding)
我是 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)
你可以阅读一些关于泛型的知识in the documentation, but the doc is more focused on the differences with Java (for instance regarding generic variance), rather than explaining the basics of generics. The Java documentation,正如@Tenfour04 所提到的,更有指导意义。
基本上,当 class 的代码除了 class 的某些 input/output 值的类型之外应该相同时,泛型 classes 很有用(constructor/method 参数和 return 类型)。与仅在任何地方使用 Any
或其他父类型相比,它允许具有更多的类型安全性。
例如,这个 Box
class 可以包含任何类型的值:
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>
class 的方法,其中 T
是在实例化 class 时决定的类型。 T
据说是 Box
class 的 类型参数 。 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
,但有时您希望 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
您还可以在泛型 class 中声明多个类型参数,方法是用逗号分隔它们:
interface Map<K, V>
每个类型参数也可以有自己的界限,这就是导致您看到的语法的原因:
abstract class BaseVMActivity<VM : ViewModel , B : ViewBinding>
在这种情况下,有2个类型参数,VM
和B
,它们必须分别是ViewModel
和ViewBinding
的子类型。
我是 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)
你可以阅读一些关于泛型的知识in the documentation, but the doc is more focused on the differences with Java (for instance regarding generic variance), rather than explaining the basics of generics. The Java documentation,正如@Tenfour04 所提到的,更有指导意义。
基本上,当 class 的代码除了 class 的某些 input/output 值的类型之外应该相同时,泛型 classes 很有用(constructor/method 参数和 return 类型)。与仅在任何地方使用 Any
或其他父类型相比,它允许具有更多的类型安全性。
例如,这个 Box
class 可以包含任何类型的值:
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>
class 的方法,其中 T
是在实例化 class 时决定的类型。 T
据说是 Box
class 的 类型参数 。 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
,但有时您希望 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
您还可以在泛型 class 中声明多个类型参数,方法是用逗号分隔它们:
interface Map<K, V>
每个类型参数也可以有自己的界限,这就是导致您看到的语法的原因:
abstract class BaseVMActivity<VM : ViewModel , B : ViewBinding>
在这种情况下,有2个类型参数,VM
和B
,它们必须分别是ViewModel
和ViewBinding
的子类型。