【问题标题】:How does protocol extension work in Swift?协议扩展在 Swift 中是如何工作的?
【发布时间】:2019-11-05 11:41:14
【问题描述】:

我正在开始一个新的 iOS Swift 项目。我需要添加一些所有项目类都应该继承的功能。与Objective C 不同,并非Swift 中的所有类都继承自任何特定类,即NSObject。例如,

我无法创建 AnyAnyObject 类的扩展,就像我可以创建 NSObject 一样。比如下面的代码就OK了。

extension NSObject {

    @objc var classTag: String {
        return String(describing: type(of: self))
    }
}

但是,AnyObject 上的扩展会导致编译器错误,

不能扩展非标称类型'AnyObject'

所以,我决定让我的项目中的所有 swift 类都继承自 BaseClass,而 BaseClass 实际上是继承自 NSObject

class BaseClass: NSObject {

    @objc var classTag: String {
        return String(describing: type(of: self))
    }
}

和其他类,即

class OtherClass: BaseClass {
    // have classTag
}

在我为我的团队制定策略,从BaseClass 继承所有类之前,我想知道默认从NSObject 继承所有类是否有一些缺点。

【问题讨论】:

  • 你应该改用协议和结构
  • 如果您使用 Swift 编程,我认为任何类都绝对没有理由从 NSObject 继承,除非有一些特殊的依赖项需要它。为什么还要将您的设计锁定为所有类都有一个超类?
  • @JoakimDanielson 正如我所说,我可能需要强加我的项目类的一些通用功能。 classTag 只是一个例子。甚至可能是为了未来。

标签: ios swift inheritance nsobject swift-protocols


【解决方案1】:
  • 从 NSObject 继承的类不能是final。在开启整个模块优化的同时,Swift 会尽可能添加 final,但不会在目标 c 类中添加。这是微优化,除非您有特殊情况,否则我真的不会考虑。
  • 在考虑使用复制语义(使用结构)时,您将无法通过继承来扩展结构。
  • 您会在 IDE 的自动完成中添加很多噪音。
  • 使用协议 (POP) 可以为您提供更大的灵活性/功能。像条件一致性等......如果需要,您可以扩展 NSObject 。

考虑使用protocol extension,也可以使用结构代替NSObject

protocol Base {
  func work()
}

extension Base {
  func work() {...}
}

struct AppState: Base {}

AppState().work()

【讨论】:

    【解决方案2】:

    如果您要让BaseClass 被其他类继承,我认为甚至不需要从NSObject 继承。

    您可以简单地在BaseClass 本身中添加classTag,即

    class BaseClass {
        var classTag: String {
            return String(describing: type(of: self))
        }
    }
    
    class SubClass: BaseClass {
        func someFunc() {
            print(self.classTag)
        }
    }
    

    另一种选择是使用protocolprotocol extension 并提供classTag 的默认定义,即

    protocol SomeProtocol {
        var classTag: String { get }
    }
    
    extension SomeProtocol {
        var classTag: String {
            return String(describing: type(of: self))
        }
    }
    

    然后,您可以在任何需要的地方使 SomeProtocol 符合类,即

    class SubClass: SomeProtocol {
        func someFunc() {
            print(self.classTag)
        }
    }
    

    无论如何,从 NSObject 继承是不必要的,因为您不需要任何 NSObject 特定功能。

    【讨论】:

    • 对于协议,所有子类都需要实现 someFunc() 对吗?但是我可以通过基类中的默认函数来减少他们的一些任务?
    • 不,他们不会。这就是协议扩展的用途。
    • @SazzadHissainKhan 您应该更喜欢使用结构而不是类。仅当您需要创建共享实例(单例)或需要对现有类进行子类化时才使用类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-24
    • 2015-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多