在Scala中,泛型类的类型参数使用方括号 []
声明,语法和使用方式与Java类似但更灵活。以下是Scala泛型类中使用类型参数的详细示例:
// 1. 基本泛型类定义
class Box[T](val content: T) {// 可以直接使用类型参数T作为方法参数或返回值类型def getContent: T = content// 泛型方法:接受另一个T类型参数并返回新的Boxdef combine(other: T): Box[(T, T)] = new Box((this.content, other))
}// 2. 带边界的泛型类(上界限定)
// 只能存储Number及其子类型(Int, Double等)
class NumberBox[T <: Number](val number: T) {def doubleValue: Double = number.doubleValue * 2
}// 3. 下界限定(使用>:)
class Container[T](var item: T) {// 只能放入T或其父类型的元素def put[U >: T](newItem: U): Unit = {item = newItem.asInstanceOf[T] // 安全转换}
}// 4. 协变与逆变(泛型变体)
// 协变:+T 表示List[String]是List[Any]的子类型
class ReadOnlyList[+T](val elements: List[T]) {def head: T = elements.head
}// 逆变:-T 表示Writer[Any]是Writer[String]的子类型
class Writer[-T] {def write(value: T): Unit = println(s"Writing: $value")
}// 测试代码
object GenericTest extends App {// 测试基本泛型类val stringBox = new Box("Hello Scala")val intBox = new Box(42)println(stringBox.getContent) // 输出: Hello Scalaprintln(intBox.combine(100).content) // 输出: (42,100)// 测试上界限定val intNumberBox = new NumberBox(100)val doubleNumberBox = new NumberBox(3.14)println(intNumberBox.doubleValue) // 输出: 200.0println(doubleNumberBox.doubleValue) // 输出: 6.28// 测试下界限定val stringContainer = new Container("初始值")stringContainer.put("新值") // 合法(同类型)stringContainer.put(new Object) // 合法(父类型)println(stringContainer.item) // 输出: java.lang.Object@...// 测试协变val stringList = new ReadOnlyList(List("a", "b"))val anyList: ReadOnlyList[Any] = stringList // 协变允许的赋值println(anyList.head) // 输出: a// 测试逆变val anyWriter: Writer[Any] = new Writer[Any]val stringWriter: Writer[String] = anyWriter // 逆变允许的赋值stringWriter.write("测试逆变") // 输出: Writing: 测试逆变
}
关键特性解析:
-
基本语法:
- 用
[T]
声明类型参数,如class Box[T](val content: T)
- 类型参数可用于属性、方法参数和返回值类型
- 用
-
类型边界:
- 上界限定:
T <: Number
表示T必须是Number的子类型 - 下界限定:
U >: T
表示U必须是T的父类型
- 上界限定:
-
泛型变体(独特特性):
- 协变(
+T
):如果A是B的子类型,则Box[A]
是Box[B]
的子类型 - 逆变(
-T
):如果A是B的子类型,则Box[B]
是Box[A]
的子类型 - 不变(默认):
Box[A]
和Box[B]
无父子关系
- 协变(
-
类型推断:
- Scala编译器会自动推断类型参数,如
new Box("hello")
会被推断为Box[String]
- Scala编译器会自动推断类型参数,如
Scala的泛型系统在保持类型安全的同时,通过协变、逆变等特性提供了比Java更灵活的类型转换能力,这在函数式编程场景中非常有用。