Swift 2 protocol extension not calling overridden method correctly

前端 未结 3 1311
庸人自扰
庸人自扰 2020-12-09 20:46

I\'ve been running into an issue using Swift 2\'s protocol extensions with default implementations. The basic gist is that I\'ve provided a default implementation of a proto

相关标签:
3条回答
  • 2020-12-09 21:25

    Unfortunately protocols don't have such an dynamic behavior (yet).

    But you can do that (with the help of classes) by implementing commonBehavior() in the ParentClass and overriding it in the ChildClass. You also need CommonThing or another class to conform to CommonTrait which is then the superclass of ParentClass:

    class CommonThing: CommonTrait {
        func say() -> String {
            return "override this"
        }
    }
    
    class ParentClass: CommonThing {
        func commonBehavior() -> String {
            // calling the protocol extension indirectly from the superclass
            return (self as CommonThing).commonBehavior()
        }
    
        override func say() -> String {
            // if called from ChildClass the overridden function gets called instead
            return commonBehavior()
        }
    }
    
    class AnotherParentClass: CommonThing {
        override func say() -> String {
            return commonBehavior()
        }
    }
    
    class ChildClass: ParentClass {
        override func say() -> String {
            return super.say()
        }
    
        // explicitly override the function
        override func commonBehavior() -> String {
            return "from child class"
        }
    }
    let parent = ParentClass()
    parentClass.say()          // "from protocol extension"
    let child = ChildClass()
    child.say()                // "from child class"
    

    Since this is only a short solution for your problem I hope it fits in your project.

    0 讨论(0)
  • 2020-12-09 21:34

    that is Swift's behavior. It can be good or bad, depending or your needs. Swift use static dispatch, so which method is called must be known during compilation. There are some advantages, and as usually, some disadvantages. To see, how Swift works at present time, see next very simple example. For me it looks logically ...

    protocol P {
        func foo()->Void
    }
    extension P {
        func foo()->Void {
            print("protocol foo")
        }
    }
    class A:P {
    }
    class B:A {
        func foo() {
            print("B foo")
        }
    }
    class C:B {
    
    }
    class D: C {
        // here the implementation must be overriden, 
        // due the indirect inheritance from B
        override func foo() {
            print("D foo")
        }
    }
    let a = A()      // a is A type
    a.foo()          // protocol foo
    let b = B()      // B is B type
    b.foo()          // B foo
    let p:P = B()    // p is protocol P
    // compiler is not able to know, what i would like, the dynamicType of p
    // can be everything, conforming to protocol P
    p.foo()          // protocol foo
    (p as? A)?.foo() // protocol foo
    // casting to B type, I decided, that p is B type
    (p as? B)?.foo() // B foo
    (p as? D)?.foo() // nothing is printed, becase the result of casting is nil
    
    // here the types are known at compile time
    let c = C()
    c.foo()          // B foo
    let d = D()
    d.foo()          // D foo
    let e:C = D()
    e.foo()          // D foo
    
    0 讨论(0)
  • 2020-12-09 21:35

    To simplify my lack thereof understanding what the word "Yet" means in a non-specific error. I figured out, that I can't seem write a function with arguments, in overriding extended function, and the compiler gives me an error like this, but if I write a simple function with no arguments, and make a custom implementation and call it with my overridden "simple function" It works:

    import Foundation
    import UIKit
    
    extension UIViewController {
    
        func slideInView(direction: Direction = Direction.LEFT, duration: CFTimeInterval = 0.5, closure:()->() ) {
    
            let animation               = CABasicAnimation(keyPath: "transform.translation.x")
            animation.fromValue         = self.view.bounds.width
            animation.toValue           = 0
            animation.duration          = 0.3
            animation.fillMode          = kCAFillModeForwards;
            animation.removedOnCompletion = false
    
            UIView.animateWithDuration(0.6, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
                self.view!.layer.addAnimation(animation,forKey:nil);
    
                }, completion: {(finished) -> () in
                    closure()
            });
        }
    
        func slide()  {
            self.slideInView(.LEFT,duration: 0.66) {
                print("Slide in Left Complete")
            }
        }
    }
    
    class OtherUIViewController: UIViewController {
    
    
    
        override  func slide() {
            self.slideFromBottom(.BOTTOM,duration: 0.66) {
                print("Slide in Bottom Complete")
            }
        }
    
        func slideFromBottom(direction: Direction = Direction.BOTTOM, duration: CFTimeInterval = 0.5, closure:()->() ) {
    
            let animation               = CABasicAnimation(keyPath: "transform.translation.y")
            animation.fromValue         = self.view.bounds.height
            animation.toValue           = 0
            animation.duration          = 0.3
            animation.fillMode          = kCAFillModeForwards
            animation.removedOnCompletion = false
    
            UIView.animateWithDuration(0.6, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut, animations: {
                self.view!.layer.addAnimation(animation,forKey:nil);
    
                }, completion: {(finished) -> () in
                    closure()
            });
        }
    }
    
    0 讨论(0)
提交回复
热议问题