// 定义商品基类
open class Product(val name: String)
// 书籍类,继承自Product
class Book(name: String, val author: String) : Product(name)
// 服装类,继承自Product
class Clothes(name: String, val size: String) : Product(name)
// 使用out关键字实现协变,用于只读场景
class Cart<out T : Product> {
private val items: MutableList<T> = mutableListOf()
// 添加商品到购物车
fun addItem(item: T) {
items.add(item)
}
// 获取购物车中的商品列表
fun getItems(): List<T> {
return items
}
}
// 示例使用
fun main() {
val bookCart: Cart<Book> = Cart()
bookCart.addItem(Book("Effective Kotlin", "Marina Samsonova"))
val productCart: Cart<Product> = bookCart
val products: List<Product> = productCart.getItems()
products.forEach { println(it.name) }
}
设计思路解释
- 基类和子类定义:定义了
Product
作为所有商品的基类,Book
和Clothes
继承自Product
,这样不同类型的商品就有了共同的基类,方便进行统一管理。
Cart
类设计:Cart
类使用了泛型<out T : Product>
,这里的out
关键字实现了协变。协变意味着Cart<Book>
类型的对象可以安全地赋值给Cart<Product>
类型的变量,因为Cart
类中只对T
进行读取操作(如getItems
方法返回List<T>
),而没有写入操作(如果有写入操作,就可能破坏类型安全)。
- 类型安全与协变逆变应用:通过协变,保证了不同类型商品(如
Book
、Clothes
)在Cart
中的添加和获取是类型安全的,同时利用协变优化了商品在不同场景下的传递和使用,比如可以将Cart<Book>
传递给期望Cart<Product>
的地方,因为Book
是Product
的子类型,符合协变规则。在这个例子中,购物车主要是对商品进行添加和读取,所以协变满足其设计需求。如果有需要在购物车中进行更多复杂操作(如替换商品等),可能会涉及到逆变等更复杂的类型处理,但在本题需求下,协变足以满足类型安全和优化传递使用的要求。