2.6 面向对象编程
December 6, 2025 · View on GitHub
CovScript 支持面向对象编程,提供了结构体、类、继承等特性。
2.6.1 结构体(struct)
结构体是一种轻量级的数据容器,用于组织相关的数据。
# 定义结构体
struct Point
var x = 0
var y = 0
end
# 创建结构体实例
var p1 = new Point
p1.x = 10
p1.y = 20
system.out.println("Point: (" + to_string(p1.x) + ", " + to_string(p1.y) + ")")
# 带初始值的结构体
struct Rectangle
var width = 0
var height = 0
var x = 0
var y = 0
end
var rect = new Rectangle
rect.width = 100
rect.height = 50
rect.x = 10
rect.y = 10
结构体方法
结构体可以包含方法。
struct Circle
var x = 0
var y = 0
var radius = 1
# 定义方法
function getArea()
return 3.14159 * this.radius * this.radius
end
function getCircumference()
return 2 * 3.14159 * this.radius
end
function moveTo(newX, newY)
this.x = newX
this.y = newY
end
end
var circle = new Circle
circle.radius = 5
system.out.println("Area: " + to_string(circle.getArea()))
system.out.println("Circumference: " + to_string(circle.getCircumference()))
circle.moveTo(100, 200)
system.out.println("New position: (" + to_string(circle.x) + ", " + to_string(circle.y) + ")")
2.6.2 类(class)
类是更强大的面向对象结构,支持构造函数、继承等特性。
# 定义类
class Person
var name = ""
var age = 0
function speak()
system.out.println("My name is " + this.name)
end
function introduce()
system.out.println("I am " + this.name + ", " + to_string(this.age) + " years old")
end
end
# 创建类实例
var person = new Person
person.name = "Alice"
person.age = 25
person.speak()
person.introduce()
2.6.3 构造函数(construct)
仅 ECS 支持: 构造函数 construct 是 CovScript 4 (ECS) 的特性,CSC 不支持此功能。
构造函数在对象创建时自动调用,用于初始化对象。使用构造函数可以在创建对象时直接传入参数,避免创建后再逐个设置属性。
class Student
var name = ""
var age = 0
var grade = ""
# 构造函数:在对象创建时自动调用
function construct(n, a, g)
this.name = n
this.age = a
this.grade = g
end
function display()
system.out.println("Student: " + this.name)
system.out.println("Age: " + to_string(this.age))
system.out.println("Grade: " + this.grade)
end
end
# 使用构造函数创建对象
# **仅 ECS 支持:** 使用 new ClassName{参数列表} 语法
var student1 = new Student{"Alice", 18, "A"}
var student2 = new Student{"Bob", 19, "B"}
student1.display()
student2.display()
默认构造函数
class Book
var title = "Untitled"
var author = "Unknown"
var pages = 0
# 默认构造函数
function initialize()
this.title = "Default Book"
this.author = "Default Author"
this.pages = 100
end
function info()
system.out.println(this.title + " by " + this.author + " (" + to_string(this.pages) + " pages)")
end
end
var book = new Book
book.info()
重要说明: 即便定义了 construct 构造函数,initialize 默认构造函数依然会先被调用。调用顺序为:
- 先调用
initialize()进行默认初始化 - 再调用
construct(参数)进行参数化初始化
这个设计确保了对象的基本状态总是被正确初始化
2.6.4 继承(extends)
类可以继承另一个类的属性和方法。
# 基类
class Animal
var name = ""
var age = 0
function construct(n, a)
this.name = n
this.age = a
end
function makeSound()
system.out.println("Some sound...")
end
function info()
system.out.println("Name: " + this.name + ", Age: " + to_string(this.age))
end
end
# 派生类
class Dog extends Animal
var breed = ""
function construct(n, a, b) override
# 调用父类构造函数(通过手动设置)
this.name = n
this.age = a
this.breed = b
end
function makeSound() override
system.out.println("Woof! Woof!")
end
function fetch()
system.out.println(this.name + " is fetching the ball!")
end
end
class Cat extends Animal
var color = ""
function construct(n, a, c) override
this.name = n
this.age = a
this.color = c
end
function makeSound() override
system.out.println("Meow! Meow!")
end
function climb()
system.out.println(this.name + " is climbing the tree!")
end
end
# 使用继承
var dog = new Dog{"Buddy", 3, "Golden Retriever"}
dog.info()
dog.makeSound()
dog.fetch()
var cat = new Cat{"Whiskers", 2, "Orange"}
cat.info()
cat.makeSound()
cat.climb()
2.6.5 方法重写(override)
子类可以重写父类的方法。
class Shape
var color = "white"
function construct(c)
this.color = c
end
function draw()
system.out.println("Drawing a shape")
end
function getArea()
return 0
end
end
class Square extends Shape
var side = 0
function construct(c, s) override
this.color = c
this.side = s
end
# 重写父类方法
function draw() override
system.out.println("Drawing a " + this.color + " square")
end
function getArea() override
return this.side * this.side
end
end
class Circle extends Shape
var radius = 0
function construct(c, r) override
this.color = c
this.radius = r
end
# 重写父类方法
function draw() override
system.out.println("Drawing a " + this.color + " circle")
end
function getArea() override
return 3.14159 * this.radius * this.radius
end
end
# 多态
var shapes = {new Square{"red", 5}, new Circle{"blue", 3}}
foreach shape in shapes
shape.draw()
system.out.println("Area: " + to_string(shape.getArea()))
end
2.6.6 this 关键字
this 关键字引用当前对象实例。
class Counter
var count = 0
function increment()
this.count += 1
return this # 返回当前对象,支持链式调用
end
function decrement()
this.count -= 1
return this
end
function reset()
this.count = 0
return this
end
function getValue()
return this.count
end
end
# 使用 this 实现链式调用
var counter = new Counter
counter.increment().increment().increment()
system.out.println(counter.getValue()) # 3
counter.reset().increment()
system.out.println(counter.getValue()) # 1
2.6.7 指针操作
引用操作符(&)
获取对象的引用。
class Data
var value = 0
function construct(v)
this.value = v
end
end
var obj = new Data{42}
# 获取引用
var ref = &obj
# 通过引用修改
ref.value = 100
system.out.println(obj.value) # 100
箭头操作符(->)
访问指针指向对象的成员。
class Node
var data = 0
var next = null
function construct(d)
this.data = d
this.next = null
end
end
var node1 = new Node{1}
var node2 = new Node{2}
node1.next = node2
# 访问对象成员(使用点运算符)
var nextNode = node1.next
system.out.println(nextNode.data) # 2
# 链式访问
if node1.next != null
system.out.println(node1.next.data)
end
# 如果使用 gcnew 创建指针,则使用箭头运算符
var ptrNode = gcnew Node{3}
system.out.println(ptrNode->data) # 3
解引用操作符(*)
获取指针指向的值。
var x = 42
var ptr = gcnew x
# 解引用
var value = *ptr
system.out.println(value) # 42
# 通过指针修改值
*ptr = 100
system.out.println(*ptr) # 100
2.6.8 完整示例:链表实现
class Node
var data = null
var next = null
function construct(d)
this.data = d
this.next = null
end
end
class LinkedList
var head = null
var size = 0
function construct()
this.head = null
this.size = 0
end
function append(data)
var newNode = gcnew Node{data}
if this.head == null
this.head = newNode
else
var current = this.head
loop
if current->next == null
current->next = newNode
break
end
current = current->next
end
end
this.size += 1
end
function display()
if this.head == null
system.out.println("List is empty")
return
end
var current = this.head
var output = ""
loop
output += to_string(current->data)
if current->next != null
output += " -> "
current = current->next
else
break
end
end
system.out.println(output)
end
function getSize()
return this.size
end
end
# 使用链表
var lst = new LinkedList
lst.append(1)
lst.append(2)
lst.append(3)
lst.append(4)
system.out.println("List size: " + to_string(lst.getSize()))
lst.display()
面向对象编程最佳实践
- 封装:隐藏内部实现细节,只暴露必要的接口
- 单一职责:每个类应该只有一个职责
- 组合优于继承:优先使用组合而不是继承来复用代码
- 使用有意义的命名:类名、方法名应该清晰表达其用途
- 保持类的简洁:避免过大的类,适时拆分
# 好的设计示例
class BankAccount
var balance = 0
var accountNumber = ""
function construct(accNum, initialBalance)
this.accountNumber = accNum
this.balance = initialBalance
end
function deposit(amount)
if amount > 0
this.balance += amount
return true
end
return false
end
function withdraw(amount)
if amount > 0 && amount <= this.balance
this.balance -= amount
return true
end
return false
end
function getBalance()
return this.balance
end
end