user3067870
user3067870

Reputation: 596

Returning a subclass from its base class in swift

I am trying to allow a method in a super class to return an instance of the subclass so that I can use method chaining with methods across both the parent and the child.

However, I am getting the error "BaseClass does not have a member named someOtherChainableMethod" when I attempt to chain the methods. Here is my code:

class BaseClass {
    func someChainableMethod() -> BaseClass {
        return self
    }
}

class ChildClass: BaseClass {
    func someOtherChainableMethod() -> ChildClass {
        return self
    }
}

let childClass = ChildClass

childClass.someChainableMethod().someOtherChainableMethoid()

The issue seems to be that the 'return self' in the parent chain-able method is returning an instance with type BaseClass rather than ChildClass.

I have also tried this with generics and failed, this is what I tried:

class BaseClass<T> {
    func someChainableMethod() -> T {
        return self
    }
}

class ChildClass: BaseClass<ChildClass> {
    func someOtherChainableMethod() -> ChildClass {
        return self
    }
}

let childClass = ChildClass

childClass.someChainableMethod().someOtherChainableMethoid()

In this case the error from the BaseClass someChainableMethod method, is "BaseClass is not convertible to T".

Upvotes: 11

Views: 3916

Answers (4)

Rein rPavi
Rein rPavi

Reputation: 3396

Simply override the base class someChainableMethod

class BaseClass {
    func someChainableMethod() -> Self{
        return self
    }
}

class ChildClass: BaseClass {
    override func someChainableMethod() -> Self {
        return self
    }
    func A(){

    }
}

var objChild = ChildClass()
objChild.someChainableMethod()

Upvotes: 0

Martin R
Martin R

Reputation: 539745

Your code works if you change the return type of the methods to Self:

class BaseClass {
    func someChainableMethod() -> Self {
        return self
    }
}

class ChildClass: BaseClass {
    func someOtherChainableMethod() -> Self {
        return self
    }
}

let childClass = ChildClass()
let foo = childClass.someChainableMethod().someOtherChainableMethod()

Upvotes: 14

Carmine Noviello
Carmine Noviello

Reputation: 11

Since you already know that childClass is an instance of ChildClass, you can do

(childClass.someChainableMethod() as ChildClass).someOtherChainableMethoid()

Upvotes: 0

Ken Kuan
Ken Kuan

Reputation: 798

Add someOtherChaingableMethod in your base class and left a empty implementation.

Upvotes: 0

Related Questions