You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无Nib的UIView子类是否违反里氏替换原则及SOLID?

这个NiblessView是否违反SOLID原则?尤其是里氏替换原则?

结论:确实违反了里氏替换原则(LSP),但属于iOS开发中常见的架构权衡选择

里氏替换原则的核心是:子类必须能够替换父类,且不会破坏原有代码的正确性。UIView作为父类,其公开契约包含了通过nib/故事板加载的能力——也就是init?(coder:)初始化器的可用性。任何依赖UIView的代码,都有理由认为可以通过这个初始化器创建实例。

你的NiblessView实现中,将init?(coder:)标记为unavailable并在调用时抛出致命错误,直接打破了这个契约:如果有一段代码期望接收任意UIView子类(比如通用的视图加载工具类),当传入NiblessView时会直接崩溃,这完全不符合LSP的要求。

但这个设计并非完全不可取

在依赖注入优先的架构中,禁止nib加载是一种刻意的约束:它强制开发者通过初始化器显式注入依赖,避免nib中隐含的控件绑定、属性设置等隐式依赖,从而提升代码的可测试性和可维护性。这是在SOLID原则的严格性和实际架构目标之间的权衡。

优化建议(减少LSP违反程度)

  • 不要直接标记init?(coder:)为不可用,而是在方法内部输出警告日志并返回nil,或者在类的文档注释中明确标注「该类不支持nib/故事板加载」
  • 提供清晰的类注释,明确告知开发者该类的使用场景(仅支持代码初始化)
  • 若想更贴合SOLID原则,可以考虑将「无nib加载」设计为一个协议(比如Nibless),让需要该特性的UIView子类遵循协议,而非直接继承一个限制型父类,这样更符合接口隔离原则(ISP)

你的代码示例

import UIKit

open class NiblessView: UIView {
    
    // MARK: Public Methods
    public override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    @available(*, unavailable, message: "Loading this view from a nib is unsupported in favor of initializer dependency injection.")
    public required init?(coder: NSCoder) {
        fatalError("Loading this view from a nib is unsupported in favor of initializer dependency injection.")
    }
}

内容的提问来源于stack exchange,提问作者Retro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 12:01:04