多继承系统 (Multiple Inheritance)
概述
Valkyrie 支持多继承,允许一个类同时继承多个父类。多继承使用 C3 线性化算法来解决方法解析顺序 (Method Resolution Order, MRO) 问题,确保继承的一致性和可预测性。
基本多继承语法
简单多继承
valkyrie
class A {
method_a(self) {
println("Method from A")
}
common_method(self) {
println("A's common method")
}
}
class B {
method_b(self) {
println("Method from B")
}
common_method(self) {
println("B's common method")
}
}
class C {
method_c(self) {
println("Method from C")
}
common_method(self) {
println("C's common method")
}
}
# 多继承语法:class 子类(父类1, 父类2, ...)
class MultiChild(A, B, C) {
own_method(self) {
println("MultiChild's own method")
}
}重命名继承
当多个父类有同名方法时,可以使用重命名语法来避免冲突:
valkyrie
class Display {
show(self) {
println("Display show")
}
}
class Printer {
show(self) {
println("Printer show")
}
print(self) {
println("Printing...")
}
}
# 重命名继承语法:class 子类(rename: 父类, 其他父类)
class Document(rename: Display, Printer) {
display_document(self) {
# 通过重命名访问 Display 的方法
self.rename.show() # 调用 Display::show
self.print() # 调用 Printer::print
self.show() # 调用 Printer::show (C3 线性化的第一个匹配)
}
}复杂重命名场景
valkyrie
class FileReader {
read(self) -> String {
"Reading from file"
}
close(self) {
println("Closing file")
}
}
class NetworkReader {
read(self) -> String {
"Reading from network"
}
close(self) {
println("Closing connection")
}
}
class Logger {
log(self, message: String) {
println("Log: {}", message)
}
}
# 多重重命名
class HybridReader(file_reader: FileReader, net_reader: NetworkReader, Logger) {
read_from_file(self) -> String {
let content = self.file_reader.read()
self.log(@format("Read from file: {}", content))
content
}
read_from_network(self) -> String {
let content = self.net_reader.read()
self.log(@format("Read from network: {}", content))
content
}
cleanup(self) {
self.file_reader.close()
self.net_reader.close()
}
}C3 线性化算法
Valkyrie 使用 C3 线性化算法来确定方法解析顺序:
valkyrie
class A {
method(self) { println("A") }
}
class B(A) {
method(self) { println("B") }
}
class C(A) {
method(self) { println("C") }
}
class D(B, C) {
# 没有重写 method
}
# C3 线性化顺序:D -> B -> C -> A
# 调用 d.method() 会调用 B::method
let d = new D {}
d.method() # 输出:"B"线性化顺序示例
valkyrie
class Base {
base_method(self) { println("Base") }
}
class Left(Base) {
left_method(self) { println("Left") }
common_method(self) { println("Left common") }
}
class Right(Base) {
right_method(self) { println("Right") }
common_method(self) { println("Right common") }
}
class Middle(Left, Right) {
middle_method(self) { println("Middle") }
}
class Final(Middle, Right) {
# C3 线性化:Final -> Middle -> Left -> Right -> Base
test_resolution(self) {
self.common_method() # 调用 Left::common_method
self.left_method() # 调用 Left::left_method
self.right_method() # 调用 Right::right_method
self.base_method() # 调用 Base::base_method
}
}方法访问模式
直接访问
valkyrie
class Child(A, B, C) {
test_access(self) {
# 直接调用,使用 C3 线性化顺序
self.common_method() # 调用第一个匹配的方法
# 通过重命名访问特定父类的方法
# 注意:没有 super 关键字
}
}重命名访问
valkyrie
class AdvancedChild(primary: A, secondary: B, tertiary: C) {
demonstrate_access(self) {
# 通过重命名访问特定父类
self.primary.common_method() # 调用 A::common_method
self.secondary.common_method() # 调用 B::common_method
self.tertiary.common_method() # 调用 C::common_method
# 直接访问使用 C3 线性化
self.common_method() # 调用 A::common_method (第一个)
}
}匿名类继承
Valkyrie 支持匿名类的继承:
valkyrie
# 匿名类继承
micro process_shape(shape: class(Drawable, Movable) {
area(self) -> f64
}) {
shape.draw()
shape.move_to(10.0, 20.0)
println("Area: {}", shape.area())
}
# 使用匿名类
let circle = class(Drawable, Movable) {
radius: f64,
x: f64,
y: f64,
area(self) -> f64 {
3.14159 * self.radius * self.radius
}
}
process_shape(new circle { radius: 5.0, x: 0.0, y: 0.0 })匿名类重命名继承
valkyrie
# 匿名类的重命名继承
micro create_hybrid_processor() -> class(reader: FileReader, writer: FileWriter) {
process(self, filename: String) {
let content = self.reader.read_file(filename)
let processed = content.to_uppercase()
self.writer.write_file(filename + ".processed", processed)
}
}
let processor = create_hybrid_processor() {
# 匿名类实现
}构造函数和初始化
valkyrie
class Parent1 {
value1: i32,
new(v1: i32) -> Self {
new Self { value1: v1 }
}
}
class Parent2 {
value2: String,
new(v2: String) -> Self {
new Self { value2: v2 }
}
}
class MultiInherit(Parent1, Parent2) {
own_value: f64,
# 多继承的构造函数
new(v1: i32, v2: String, own: f64) -> Self {
Self {
# 父类字段初始化
value1: v1,
value2: v2,
# 自己的字段
own_value: own,
}
}
}抽象类和接口
valkyrie
# 抽象基类
abstract class Shape {
abstract micro area(self) -> f64
abstract micro perimeter(self) -> f64
# 具体方法
describe(self) {
println("Area: {}, Perimeter: {}", self.area(), self.perimeter())
}
}
# 接口定义
trait Drawable {
draw(self)
set_color(self, color: Color)
}
# 多继承:抽象类 + 接口
class Rectangle(Shape): Drawable {
width: f64,
height: f64,
color: Color,
# 实现抽象方法
area(self) -> f64 {
self.width * self.height
}
perimeter(self) -> f64 {
2.0 * (self.width + self.height)
}
# 实现接口方法
draw(self) {
println("Drawing rectangle {}x{}", self.width, self.height)
}
set_color(self, color: Color) {
self.color = color
}
}钻石问题解决
valkyrie
class GrandParent {
method(self) { println("GrandParent") }
}
class Parent1(GrandParent) {
method(self) { println("Parent1") }
}
class Parent2(GrandParent) {
method(self) { println("Parent2") }
}
# 钻石继承
class Child(Parent1, Parent2) {
# C3 线性化自动解决钻石问题
# 线性化顺序:Child -> Parent1 -> Parent2 -> GrandParent
test_diamond(self) {
self.method() # 调用 Parent1::method
}
# 如果需要调用特定父类的方法,使用重命名
}
# 使用重命名解决钻石问题
class ResolvedChild(p1: Parent1, p2: Parent2) {
test_resolved(self) {
self.p1.method() # 明确调用 Parent1::method
self.p2.method() # 明确调用 Parent2::method
}
}最佳实践
1. 优先使用组合而非继承
valkyrie
# 好的设计:组合
class Document {
reader: FileReader,
writer: FileWriter,
logger: Logger,
process(self) {
let content = self.reader.read()
let processed = self.transform(content)
self.writer.write(processed)
self.logger.log("Document processed")
}
}
# 避免:过度继承
# class Document(FileReader, FileWriter, Logger) { ... }2. 使用重命名避免方法冲突
valkyrie
# 清晰的重命名
class MediaPlayer(audio: AudioPlayer, video: VideoPlayer) {
play_audio(self, file: String) {
self.audio.play(file)
}
play_video(self, file: String) {
self.video.play(file)
}
}3. 文档化继承关系
valkyrie
# 清晰的继承文档
↯doc("""
MultiProcessor 继承关系:
- DataProcessor: 提供数据处理能力
- NetworkHandler: 提供网络通信能力
- Logger: 提供日志记录能力
C3 线性化顺序:MultiProcessor -> DataProcessor -> NetworkHandler -> Logger
""")
class MultiProcessor(DataProcessor, NetworkHandler, Logger) {
# 实现
}总结
Valkyrie 的多继承系统特点:
- C3 线性化:确保方法解析的一致性
- 重命名机制:解决方法名冲突
- 无 super 关键字:通过重命名明确访问父类方法
- 匿名类支持:支持临时的多继承类定义
- 类型安全:编译时检查继承关系的合法性
正确使用多继承可以实现灵活的代码复用,但应该谨慎使用,优先考虑组合和接口设计。