如何在Swift中覆盖协议扩展的实例方法?

时间:2016-07-26 22:12:30

标签: ios swift protocols swift-protocols swift-extensions

我正在尝试从协议扩展中覆盖实例方法,我遇到了一些麻烦。

对于上下文,我正在制作一个包含许多不同UICollectionViews的iOS应用程序。这些视图从不同的数据库(需要不同的回调函数)获取数据,并具有非常不同的布局。因为(数据库,布局)的任何组合都是可能的,所以如果没有大量的代码重复,很难创建一个漂亮的OOP类层次结构。

我有想法将布局函数(主要是在UICollectionViewDelegateFlowLayout协议中定义的那些)放入协议扩展中,因此我可以使用扩展的协议来装饰给定的UICollectionView子类,以实现所有相关的布局函数,但我有很难过。问题的实质包含在下面的代码中。

class Base {
    func speak(){
        print("Base")
    }
}

class SubA: Base, ProtocolA {}

class SubB: Base, MyProtocolB {}

protocol MyProtocolA{
    func speak()
}

protocol MyProtocolB{
    func speak()
}

extension MyProtocolA{
    func speak(){
        print("A")        
    }
}

extension MyProtocolA{
    func speak(){
        print("B")        
    }
}

let suba = SubA()
suba.speak()  // prints "Base", I want it to print "A"

let subb = SubB()
subb.speak()  // prints "Base", I want it to print "B"

思想?

1 个答案:

答案 0 :(得分:4)

仅当符合这些协议的类未实现该方法本身时,才会调用协议中的默认实现。课程'方法会覆盖协议的默认实现,而不是相反。

通常情况下,您可以执行以下操作:

<script>
    $('a[href$=\\.pdf]').click(function() {
    var myuri = this.href ;   
        alert(this.href);

  /*alert just to make sure I got the right uri (which works fine)*/

    cordova.plugins.fileOpener2.open(
        'this.href', // You can also use a Cordova-style file uri: cdvfile://localhost/persistent/Download/starwars.pdf
        'application/pdf', 
        { 
                error : function(e) 
             { 
                alert('Error status: ' + e.status + ' - Error message: ' + e.message);
            },
            success : function () 
            {
                alert('file opened successfully');                
            }
        }
    );
        return false; 
    });

    </script>

但如果你这样做

protocol MyProtocolA {
    func speak()
}

protocol MyProtocolB {
    func speak()
}

extension MyProtocolA {
    func speak() {
        print("A")        
    }
}

extension MyProtocolB {
    func speak() {
        print("B")        
    }
}

class SubA: MyProtocolA {}

class SubB: MyProtocolB {}

let suba = SubA()
suba.speak()  // prints "A"

let subb = SubB()
subb.speak()  // prints "B"

坦率地说,在您看到这一点时,class SubC: MyProtocolA { func speak (){ print("C") } } let subc = SubC() subc.speak() // prints "C" 的使用在此示例中完全是多余的,因此我已将其删除。显然,如果您因其他原因需要从Base继承,请随意。但关键的一点是,协议默认实现不会覆盖类&#39;实施,而是反过来。