在面向对象编程中,类可以包含 抽象方法 和 非抽象方法。
这两种方法具有不同的特性和用途:
抽象方法:
定义:
- 抽象方法是没有具体实现的方法,通常只在抽象类或接口(协议)中声明。子类必须实现这些方法,以提供具体的行为。
特点:
- 在抽象类或接口中声明,但没有方法体;
- 任何继承抽象类或者实现接口的子类都必须提供这些方法的具体实现;
- 用于定义一组强制的行为规范,让所有的子类遵循;
使用场景:
- 当你希望强制所有子类实现某些方法时;
- 当你希望在子类中提供具体的实现,而不是在基类中实现;
// 定义一个类 Animal
class Animal {
// 抽象方法(没有具体实现,要求子类实现)
func makeSound() -> String {
fatalError("子类需要实现 ‘makeSound()’ 方法")
}
}
// 定义一个子类
class Dog: Animal {
// 提供 makeSound 方法的具体实现
override func makeSound() -> String {
return "Bark"
}
}
let dog = Dog()
print(dog.makeSound()) // 输出'Bark'
非抽象方法:
定义:
- 非抽象方法是在类中实现了具体行为的方法。它们可以在基类中提供实现,也可以在子类中重写(如果需要);
特点:
- 具有方法体,并提供具体的实现;
- 可以被子类继承而不改变其行为,也可以在子类中被重写;
- 用于提供类的具体功能和行为;
使用场景:
- 当你希望基类提供一个默认的实现,子类可以选择是否重写;
- 当你希望提供公共的功能,所有子类都可以直接使用或修改;
// 定义一个类 Animal
class Animal {
// 非抽象方法,提供默认实现
func makeSound() -> String {
return "一些常见的动物叫声"
}
}
// 定义一个子类
class Cat: Animal {
// 重写 makeSound 方法,提供特定实现
override func makeSound() -> String {
return "Meow"
}
}
let cat = Cat()
print(cat.makeSound()) // 输出'Meow'
综合示例:
// 定义一个类
class Shape {
// 非抽象方法,提供默认的描述
func description() -> String {
return "this is a shape."
}
// 抽象方法,要求子类实现
func area() -> Double {
fatalError("子类需要实现‘area()’方法")
}
}
// 定义一个子类
class Circle: Shape {
var radius: Double
init(radius: Double) {
self.radius = radius
}
// 提供 area 方法的具体实现
override func area() -> Double {
return .pi * radius * radius
}
// 可以选择重写 description 方法(可选)
override func description() -> String {
return "This is a cicle with radius \(radius)"
}
}
let circle = Circle(radius: 5)
print(circle.description()) // 输出:This is a cicle with radius 5.0
print("Area: \(circle.area())")// 输出:Area: 78.53981633974483
总结
- 抽象方法:没有实现的声明方法,子类必须实现这些方法以提供具体行为。
- 非抽象方法:在基类中提供了具体实现的方法,子类可以继承这些实现,或者根据需要重写它们。