7

Supposing to have this three classes with this simply hierarchy:

class A {
    func foo() {
       print("A")
    }
}

class B: A {
    override func foo() {
       super.foo()
       print("B")
    }
}

class C: B {
    override func foo() {
       // *******
       print("C")
    }
}

In class C, in overrided method foo I want to call a method foo: is it possible?

In C++ this can be achieved with C->A::foo(), but how do I do this in Swift?

JAL
  • 41,701
  • 23
  • 172
  • 300
Luca Davanzo
  • 21,000
  • 15
  • 120
  • 146
  • 2
    `super.super.foo()`. – Tobi Nary Mar 08 '16 at 15:02
  • I tried `super.super.foo()` and it doesn't compile – EmilioPelaez Mar 08 '16 at 15:05
  • Was the first thing I tried and did not work, definitely! – Luca Davanzo Mar 08 '16 at 15:06
  • This is intentionally hidden. There is absolutely no need for `C` to access the original declaration of `A` in any sane object architecture – Sulthan Mar 08 '16 at 15:08
  • 1
    By thy way, the reason why in C++ this is possible is due to multiple inheritance. `super` is not enough in C++ so they had to allow to specify the base class explicitly. Using implementation that has been overriden by superclass seems like a very very bad idea. – Sulthan Mar 08 '16 at 15:17
  • Additionally, the Objective-C runtime (and Swift) does not support multiple inheritance. Use protocols, expose an accessor, or get an opaque pointer to the superclass's superclass and fire the selector. – JAL Mar 08 '16 at 15:20

1 Answers1

15

super.foo() should be sufficient, since B prints "B" and calls super to print "A".

class C: B {
    override func foo() {
        super.foo()
        print("C")
    }
}

let c = C()
c.foo()

Output:

A
B
C

If you want to intentionally expose A's foo() from B, you need to create a new accessor:

class B: A {
    override func foo() {
        super.foo()
        print("B")
    }

    func exposeFoo() {
        super.foo()
    }
}

class C: B {
    override func foo() {
        super.exposeFoo()
        print("C")
    }
}

Or, use NSObject and the power of the Objective-C runtime:

class A: NSObject { // make sure your base class inherits from NSObject
    func foo() {
        print("A")
    }
}

// ...

class C: B {
    override func foo() {

        guard let superSuper = self.superclass?.superclass() else {
            return; // no super super
        }

        let fooImp = class_getMethodImplementation(superSuper, "foo")

        typealias MyCFunction = @convention(c) (AnyObject, Selector) -> Void
        let curriedImplementation = unsafeBitCast(fooImp, MyCFunction.self)
        curriedImplementation(self, selector) // prints A
    }
}
JAL
  • 41,701
  • 23
  • 172
  • 300
  • I already think to adopt this way, but I can explain why I can't call A::foo explicitly – Luca Davanzo Mar 08 '16 at 15:11
  • 1
    @Velthune read [this](http://stackoverflow.com/q/5102847/2415822). If you can inherit from `NSObject` you can access the object's `superclass` and use the Objective-C runtime to create a `COpaquePointer` to the superclass's superclass and fire A's `foo` selector. Multiple inheritance is not supported. – JAL Mar 08 '16 at 15:20
  • 1
    Notable, very notable! Thanks for the link and tips! – Luca Davanzo Mar 08 '16 at 15:26