构造器注入
通过初始化器传递依赖。
构造器注入 是 CoddyKit 上的免费 Swift Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Swift Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Swift Academy 课程共包含 4 节课。
构造器注入
最常见的 DI 风格是通过初始化器传入依赖。对象在创建时接收所需的一切,并将其保存起来。
基本初始化器
声明一个存储属性,并在 init 中为其赋值。调用方必须提供依赖才能创建对象。
struct Greeter { func hi() -> String { "Hi" } }
struct View {
let greeter: Greeter
init(greeter: Greeter) { self.greeter = greeter }
func show() { print(greeter.hi()) }
}
View(greeter: Greeter()).show()不可变依赖
对注入的属性使用 let 会使其不可变,因此依赖在构造完成后无法被替换。
struct Engine { let hp: Int }
struct Car {
let engine: Engine // cannot change later
init(engine: Engine) { self.engine = engine }
}
let c = Car(engine: Engine(hp: 150))
print(c.engine.hp)多个依赖
列出多个参数即可注入多个协作者。初始化器会记录完整的需求集合。
struct DB { func get() -> Int { 7 } }
struct Cache { func put(_ v: Int) { print("cached \(v)") } }
struct Service {
let db: DB
let cache: Cache
init(db: DB, cache: Cache) { self.db = db; self.cache = cache }
func run() { cache.put(db.get()) }
}
Service(db: DB(), cache: Cache()).run()默认参数值
默认值允许调用方在生产环境中省略某个依赖,同时仍可在测试中覆盖它。
struct Logger { func log(_ m: String) { print(m) } }
struct Service {
let logger: Logger
init(logger: Logger = Logger()) { self.logger = logger }
func run() { logger.log("go") }
}
Service().run() // uses default类的构造器注入
类也遵循相同的模式。初始化器会在实例可用之前为每个依赖赋值。
class Mailer { func send() { print("sent") } }
class Signup {
let mailer: Mailer
init(mailer: Mailer) { self.mailer = mailer }
func go() { mailer.send() }
}
Signup(mailer: Mailer()).go()注入值
依赖不一定是对象。您也可以用相同的方式注入基础 URL 或标志等配置值。
struct Client {
let baseURL: String
init(baseURL: String) { self.baseURL = baseURL }
func endpoint(_ p: String) -> String { baseURL + p }
}
print(Client(baseURL: "https://api").endpoint("/users"))组合根
在应用入口附近设置一个位置,用于连接整个对象图。其他部分只需接收已经准备好的依赖。
struct DB { func count() -> Int { 3 } }
struct Repo { let db: DB; func n() -> Int { db.count() } }
struct App { let repo: Repo; func run() { print(repo.n()) } }
// Composition root:
let app = App(repo: Repo(db: DB()))
app.run()避免隐藏的全局变量
构造器注入可以取代对隐藏全局变量的访问。每个依赖都清晰可见,因此您可以追踪数据的流动方式。
struct Settings { let theme: String }
struct Screen {
let settings: Settings
func render() { print("Theme: \(settings.theme)") }
}
Screen(settings: Settings(theme: "dark")).render()必需依赖与可选依赖
如果某个依赖确实是可选的,就用可选类型表示;否则应将其设为必需依赖,确保对象不会处于配置不完整的状态。
struct Analytics { func track() { print("tracked") } }
struct Flow {
let analytics: Analytics?
func step() { analytics?.track() }
}
Flow(analytics: Analytics()).step()
Flow(analytics: nil).step()为何采用构造器注入
它能保证对象完成初始化,使依赖清晰可见,并与 let 的不可变性配合使用。在 Swift 中,它是推荐的默认方式。
struct Adder { func add(_ a: Int, _ b: Int) -> Int { a + b } }
struct Calc {
let adder: Adder
init(adder: Adder) { self.adder = adder }
}
print(Calc(adder: Adder()).adder.add(4, 5))快速检查
为什么通常更倾向于使用构造器注入?
回顾
构造器注入通过 init 传入依赖,并将其保存起来,通常保存为不可变的 let 属性。您可以注入对象或值,提供默认值,并在组合根中连接所有内容。下一步,您将注入协议,而不是具体类型。
用 AI 导师学习 Swift — 免费
在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。
- 课程
- 122
- 课程
- 409
常见问题解答
「构造器注入」课时是免费的吗?
是的 — 「构造器注入」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Swift Academy 课程的其余内容,请升级到 CoddyKit PRO。 Swift Academy 课程共包含 4 节课。
「构造器注入」这节课中我会学到什么?
通过初始化器传递依赖。 你通过在浏览器中直接运行的动手代码来练习 Swift Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Swift Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Swift Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「构造器注入」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Swift Academy 课中编写并运行代码吗?
能。每节 Swift Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。