【问题标题】:Can a Swift class be extended multiple times with the same methods?可以使用相同的方法多次扩展 Swift 类吗?
【发布时间】:2016-05-05 03:30:46
【问题描述】:

我正在设计一个使用协议和扩展的框架,以允许第三方将我的框架的支持添加到他们现有的类中。

我还想为 UIView 等已知类添加一些内置扩展,但我不想阻止用户为相同的类定义自己的额外支持。

我的问题是有什么方法可以扩展同一个类两次,并且两次都覆盖该类中的相同(协议)方法,同时如果第一个失败,仍然有一些方法可以调用另一个。

阐述:我真的有三个目标要实现:

  1. 我想让我的框架的用户为他们自己的(或任何)UIView 子类提供他们自己的扩展。
  2. 我还需要一些方法来允许可应用于所有 UIView 的通用行为作为后备​​选项(即,如果特定类扩展无法处理它,则使用通用 UIView 扩展)。
  3. 我还想通过提供一些内置的通用视图处理来分离我自己的实现,但这样做不会阻止第三方也定义他们自己的额外通用处理。 (如果我做不到,也没什么大不了的,前两部分是最重要的。)

我已经完成了第 1 部分。问题是如何实现这种回退行为。如果我用扩展来做这一切,子类将覆盖超类对协议方法的实现。它可以调用super.method,但我想避免把这个责任放在子类身上(以防作者忘记调用super)。

我想从框架代码中完成这一切:首先,调用对象的协议方法。如果它返回 false,我想以某种方式调用通用 UIView 处理程序。

现在我已经全部输入了,我想知道我是否可以为通用后备使用不同的方法并完成它。我只是想如果我能用一种方法来完成这一切会很优雅。

【问题讨论】:

  • 例子?不知道你在追求什么。协议方法是一种协议方法。只要 Type 符合协议,有什么关系呢?该协议的全部目的是添加独立于 Type 的功能。另一方面,如果您要覆盖继承的实例或 Type 方法,那么它无论如何都与协议无关。 “打电话给对方”什么?
  • 说协议定义了一种方法。我希望能够在 UIView 上提供两个扩展,每个都覆盖这个方法,但是如果一个失败(返回 false),我可以调用另一个。顺序不是很重要。
  • 我猜这属于多重继承的范畴,可能不被支持。只是想我还是会问。我确信还有另一种方法可以解决它。

标签: swift swift2


【解决方案1】:

不!不能多次延长。

extension Int {
    var add: Int {return self + 100} // Line A
}

extension Int {
    var add: Int {return self + 105} //Line B
}

这样做会产生 编译时 错误(在 B 行),指示:Invalid redeclaration of 'add'

Swift is a static typing language 并帮助您发现这些错误之前运行时


在 Objective-C 中你可以写这个并且仍然不会出错,但是 result 会是undefined,因为你不知道在运行时哪个方法首先被加载。

【讨论】:

    【解决方案2】:

    在 2 个单独的扩展中覆盖单个协议方法两次是行不通的,因为协议方法名称会发生​​冲突。编译后,它们都只是同一个类的方法。考虑到这一点,也许将所有协议方法放在他们自己的扩展中并从其他方法中调用它们?

    以下可能是一种通用选项。如果您决定继续添加额外的扩展功能,可能会变得一团糟。

        class baseClass {
               //stuff
        }
    
        extension baseClass: myProtocol {
    
            override func myProtocolMethod(args) -> returnType {
               //Repeat this in a separate extension & your method names collide     
                var status: Bool
    
              //protocol method code sets status as appropriate... 
    
              return status = true ? optOne(status) : optTwo(status)                 
    
            }
    
            func optOne(status:Bool) -> returnType{
                //do the 'true' thing
                return returnType
            }
    
            func optTwo(status:Bool) -> returnType{
                //do the 'false' thing
                return returnType
            }
        } 
    
        extension baseClass {
            var oneExtension = myProtocolMethod(someArg)
        }
    
        extension baseClass {
            var twoExtension = myProtocolMethod(someArg)
        }
    

    【讨论】:

    • 谢谢,根据我的阐述,这实际上给了我一个想法。与其尝试从两个不同的扩展调用 same 函数,也许我可以将协议函数分成两个不同的函数,一个用于特定的类实现,一个用于通用 UIView 回退(如果失败) .
    • 但是我仍然无法将我自己的实现分成一个类别。我猜那是不可能的。我想我需要在这件事上睡一觉,再想一想。
    【解决方案3】:

    我知道这个问题已经有一年多了,原来的发帖人可能已经转向其他事情了,但我还是想分享一个想法,也许会得到一些反馈。

    你说你想要一个可以被多次覆盖的方法。就像这个帖子中的许多人给出的那样,简短的答案是no,但长答案是yes

    我们可以用一点通用魔法来解决这个问题。

    class MyView: UIView {
        var customizer: MyProtocol<MyView> = Defaults()
    
        func willCallCustomizer() {
            customizer.coolMethod(self)
        }
    }
    
    // Use this class as if it were a protocol
    class MyProtocol<T: UIView>: NSObject {
        func coolMethod(_ view: T) {}
    }
    
    // Class inherits from the "protocol" 
    class Defaults: MyProtocol<MyView> {
        override func coolMethod(_ view: MyView) {
            // Some default behavior
        }
    }
    

    /// 在客户端...

    class CustomerCustomizer: MyProtocol<MyView> {
        override func coolMethod(_ view: MyView) {
            // customized behavior
        }
    }
    

    所以如果客户想使用他们自己的定制器,他们可以设置它,否则它将使用默认的。

    myViewInstance.customizer = CustomerCustomizer()
    

    这种方法的好处是客户可以根据需要多次更改定制器对象。因为 MyProtocol 是通用的,它也可以用于其他 UIView;从而完成协议的作用。

    【讨论】:

      猜你喜欢
      • 2016-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多