Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass a parent instance to a child's type variable in swift

Tags:

swift

I want to pass an instance of a parent class to a variable whose type is a subclass of this parent.

There are two classes as follow:

class Parent{
    var aaa:String?
    var bbb:String?
    init(pa:String?,pb:String?){
        self.aaa=pa
        self.bbb=pb
    }
}

class Child:Parent{
    var ccc:String?
}

Now, I use them like this:

let p=Parent(a:"1111",b:"22222")
if let c=p as? Child{
   print(c)
}

But the variable is nil in any cases.

I would like to get the result as follow: c.aaa="1111" c.bbb="222" c.ccc=nil or other

like image 704
RonnieLee Avatar asked Aug 17 '16 10:08

RonnieLee


Video Answer


2 Answers

First of all let's clean up your code

class Parent {
    var a:String?
    var b:String?
    init(a:String?, b:String?) {
        self.a = a
        self.b = b
    }
}

class Child: Parent{
    var c: String?
}

Answer

With this code you create a Parent object and you put it into the parent constant.

let parent = Parent(a:"1111",b:"22222")

Then you try to cast parent as Child. But Parent is NOT a Child. So the cast will fail.

if let child = parent as? Child {
    print(child)
}

Conclusion

class Child: Parent { ...}

you are saying that a Child is also a Parent.

NOT that a Parent is a Child.

Update

If you want to create a Child object using a Parent object (if this makes sense for your business logic) here's the code

class Child: Parent{
    var c: String?

    init(parent:Parent, c:String) {
        super.init(a: parent.a, b: parent.b)
        self.c = c
    }        
}

let parent = Parent(a: "a", b: "b")
let child = Child(parent: parent, c: "c")
child.a // "a"
child.b // "b"
child.c // "c"

has-a instead of is-a

Another possible solution is avoiding subclassing, here's the code

struct Parent {
    var a:String?
    var b:String?
}

struct Child {
    var c: String?
    var parent: Parent
}

Now Child is not a Parent but contains a Parent

You probably should rename them

Now given a parent

let parent = Parent(a: "a", b: "b")

you can easily create a Child

let child = Child(c: "c", parent: parent)

And this is how you use the child

child.parent.a // "a"
child.parent.b // "b"
child.c // "c"
like image 118
Luca Angeletti Avatar answered Oct 17 '22 00:10

Luca Angeletti


The comments in response to your question will tell you why your conditional cast will always fail. To print out the value of c as an instance of Child, the following should work:

class Parent {
    var aaa:String?
    var bbb:String?

    init(aaa: String?, bbb: String?) {
        self.aaa = aaa
        self.bbb = bbb
    }
}

class Child : Parent {
    var ccc:String?
}

var child = Child(aaa: "", bbb: "")
print(child)
like image 27
Yasir Avatar answered Oct 17 '22 01:10

Yasir