关键字 — 关键字 required

在 Swift 中,required 关键字用于修饰类的构造器(initializer),表示这个构造器在子类中必须被实现。

关键点 #

  • required 修饰的构造器必须在所有继承该类的子类中被实现。
  • 如果子类不自定义实现这个构造器,Swift 会自动继承并提供默认实现。
  • 这个关键字通常与支持继承的类(非 final 修饰的类)相关,以确保子类拥有某些特定的初始化逻辑。

语法 #

class Parent {
    required init() {
        // 实现构造逻辑
    }
}

class Child: Parent {
    required init() {
        // 子类实现
        super.init()
    }
}

required 的主要特点和用途 #

  1. 确保子类具有特定的初始化行为

    • 当你在一个父类中定义一个通用构造器,需要所有继承的子类都实现该构造器时,可以使用 required 修饰。
    • 若父类构造器定义了初始化逻辑,你可以用 required 确保子类也具有相同的行为。
  2. 可与convenienceoverride同时使用

    • required 可以与其他修饰符(如 overrideconvenience)搭配使用,但需要注意它的限制(见“注意事项”)。
  3. 强制遵守特定协议

    • 如果父类需要在初始化阶段完成某些协议要求,可以通过 required 保证构造器一致性。

应用场景与示例代码 #

1. 基本示例:强制子类实现构造器 #

class Animal {
    required init() {
        print("Animal initialized")
    }
}

class Dog: Animal {
    required init() {
        print("Dog initialized")
        super.init()
    }
}

let dog = Dog()
// 输出:
// Dog initialized
// Animal initialized
  • Animal 类中,构造器 init() 被标记为 required
  • 子类 Dog 必须实现该构造器,并调用父类的构造器(通过 super.init())。

2. 协议和子类一致性 #

如果父类的构造器需要处理协议相关的行为,可以通过 required 确保该构造器在子类中的实现:

protocol Identifiable {
    init(id: Int)
}

class Person: Identifiable {
    let id: Int
    
    // Required 构造器
    required init(id: Int) {
        self.id = id
        print("Person initialized with id: \(id)")
    }
}

class Employee: Person {
    required init(id: Int) {
        print("Employee initialized!")
        super.init(id: id)
    }
}

let employee = Employee(id: 100)
// 输出:
// Employee initialized!
// Person initialized with id: 100
  • Identifiable 协议要求实现一个带参数的构造器 init(id:)
  • Person 类使用 required 确保它的所有子类都必须实现该协议构造器。

3. 子类自动继承父类的 required 构造器 #

子类可以自动继承父类的 required 构造器(如果子类不重载的话)。例如:

class Shape {
    required init() {
        print("Shape initialized")
    }
}

class Circle: Shape {
    // 不需要手动定义 init(),自动继承父类的 required init()
}

let circle = Circle()
// 输出:
// Shape initialized

如果子类不对 required init() 进行自定义实现,那么 Swift 自动继承父类的实现。


4. 搭配其他修饰符(overrideconvenience #

  • 如果子类需要自定义 required 构造器,同时做更多初始化逻辑,可以使用 override 修饰。
  • convenience 构造器也可以与 required 配合使用。
class Vehicle {
    required init() {
        print("Vehicle initialized")
    }
}

class Car: Vehicle {
    // 子类自定义提供附加逻辑,必须使用 override
    required override init() {
        print("Car initialized")
        super.init()
    }
}

let car = Car()
// 输出:
// Car initialized
// Vehicle initialized

如果构造器是一个 convenience 方便构造器,可以这样写:

class Plane: Vehicle {
    required convenience init() {
        print("Convenience Plane initialized")
        self.init(engineCount: 2)
    }
    
    init(engineCount: Int) {
        print("Plane initialized with \(engineCount) engines")
    }
}

let plane = Plane()
// 输出:
// Convenience Plane initialized
// Plane initialized with 2 engines

注意事项 #

  1. 必须覆盖基类的 required 构造器

    • 如果基类标记了一个构造器为 required,则其所有子类都需要实现该构造器(或者继承它)。
  2. final 类不能使用 required

    • 如果类被声明为 final(表示无法被继承),则 required 的语义没有意义,因为无法有子类。
  3. required 与协议初始化

    • 如果父类或协议定义了一个构造器协议要求,required 可确保实现一致性,但需要额外考虑协议的初始化逻辑。

总结 #

  • required 用于修饰父类中的构造器,表示其子类必须实现该构造器,保证初始化行为的一致性。
  • 子类可以通过 override 自定义实现,也可以自动继承父类的实现。
  • 主要用于设计需要某些类必须包含特定初始化行为的场景,比如协议约定初始化逻辑或者框架设计。

在需要为类的设计提供更多强约束时,required 是一个强大且灵活的工具,有助于保证继承体系的安全性与一致性。

本文共 1354 字,上次修改于 Dec 25, 2024