5

Case: A base class (A) with a function (doSomething) that has a default parameter (param: T = foo), and a subclass (B) which overrides that function with a different default parameter (param: T = bar). But is then called as A.

Edit: Apologies for the original code, so actually what is happening is basically the following:

class Foo
{
    func doSomething(a: String = "123")
    {
        print(a)
    }
}

class Bar: Foo
{
    override func doSomething(a: String = "abc")
    {
        print("Using Bar method body... but not Bar's default a value!")
        print(a)
    }
}

(Bar() as Foo).doSomething()

// Prints:
// Using Bar method body... but not Bar's default a value!
// 123

Is it a bug or expected behaviour that it uses the functions body but doesn't use the functions default parameter?

  • Cannot reproduce, at least not with T replaced by String. The output is "bar" in Swift 3. Can you provide a self-contained example? – Martin R Oct 13 '16 at 15:05
  • 1
    Looked into this further and it might loosely link to a different bug that we have seen [link](http://stackoverflow.com/questions/39416385/swift-3-objc-optional-protocol-method-not-called-in-subclass) where it looks like the compiler / linker is only looking at the top level override of the function. – Joshua White Oct 13 '16 at 15:06
  • 1
    *That* one seems to be about Objective-C protocols, which I don't see in your example. Also `T` is undefined in your code. – Again: a self-contained example demonstrating the problem would be helpful. – Martin R Oct 13 '16 at 15:08
  • @MartinR Apologies for the changes (new to posting of so) - we've had a look into this further and found the cause, and it makes sense, but why would it not take Bar's parameter over Foo's. – Joshua White Oct 13 '16 at 15:25
  • Are you sure that you observed a different behavior in Swift 2? – Martin R Oct 13 '16 at 15:34
  • Thanks @MartinR, looks like it might have been - I'll correct the question – Joshua White Oct 13 '16 at 15:47

1 Answers1

2

It's being called as Foo (or A) because you tell it to. Because you're instantiating Bar() as Foo, it is doing exactly that.

If you do:

Bar().doSomething()

Bar's method is what is called:

Using Bar method body...
abc

Interestingly, as you point out:

(Bar() as Foo).doSomething()

Yields:

Using Bar method body...
123

Because Bar is instantiated as Foo, (note emphasis) Bar gets Foo's default parameters, yet still executes Bar's function body.

Interesting observation!

NonCreature0714
  • 5,744
  • 10
  • 30
  • 52