可以使用相同的方法多次扩展Swift类吗?

时间:2016-01-27 23:11:07

标签: swift swift2

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

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

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

详细说明:我想在这里实现三个目标:

  1. 我想允许我的框架用户为自己的(或任何)UIView子类提供自己的扩展。
  2. 我还需要一些方法来允许可以作为后备选项应用于所有UIViews的一般行为(即,如果特定的类扩展无法处理它,则返回到通用UIView扩展)。
  3. 我还希望通过提供一些内置的通用视图处理来分离我自己的实现,但这样做不会阻止第三方定义自己的额外通用处理。 (如果我不能这样做,那不是什么大问题,前两部分是最重要的。)
  4. 我已经完成了第1部分工作。问题是如何实现这种回退行为。如果我使用扩展来完成所有操作,子类将覆盖超类的协议方法的实现。它可以调用super.method,但我想避免将该责任放在子类上(如果作者忘记调用super)。

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

    现在我正在打字,我想知道我是否可以使用不同的方法进行通用回退并完成它。我只是觉得如果我能用一种方法做到这一点会很优雅。

3 个答案:

答案 0 :(得分:3)

没有!它不能多次扩展。

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中你可以写这个并且仍然没有收到错误,但结果将是undefined,因为你不知道哪个方法首先被加载运行。

答案 1 :(得分: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)
    }

答案 2 :(得分:1)

我意识到这个问题已经有一年多的历史了,原版海报可能已经转移到了其他方面,但我还是希望分享一个想法,或者得到一些反馈。

你说你想要一个可以多次覆盖的方法。简短的回答,就像这个帖子中的很多人所说的那样没有,但是长答案是

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

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;从而履行协议的作用。