Check if instance is protocol with types in Swift?

This is related to this issue . Using typealias, I can create a class with a "child" var, but with the specific type I'm looking for. But when I do this, I can no longer verify whether the instance should follow this protocol. I also tried "if yes" and this does not work. Is there any way to do this?

protocol Parent {
    typealias Child
    var children: [Child] { get set }
}

protocol Child {
    typealias Parent
    var parent: Parent { get set }

}

class Foo: Parent {
    var children = [Bar]()

    init(){}
}

class Bar: Child {
    var parent = Foo()
}

let testVar = Foo()
let cVar = Bar()

testVar.children.append(cVar)
cVar.parent = testVar

//I get the error here saying protocol is limited to generic constraints
if testVar is Parent { 

}
+4
source share
2 answers

, ( ). , , "" , . "" :

protocol _Parent {
    var anyChildren: [Any] { get set }
}
protocol Parent: _Parent {
    typealias Child
    var children: [Child] { get set }
}

extension Parent {
    // requirement of _Parent
    var anyChildren: [Any] {
        get {
            return children.map{ $0 as Any }
        }
        set {
            // use `as!` and `map` if you are sure that all elements are of type Child
            // or if you want a crash if not
            children = newValue.flatMap{ $0 as? Child }
        }
    }
}

protocol _Child {
    var anyParent: Any { get set }
}

protocol Child: _Child {
    typealias Parent
    var parent: Parent { get set }
}

extension Child {
    // requirement of _Child
    var anyParent: Any {
        get {
            return parent
        }
        set {
            parent = newValue as! Parent
        }
    }
}

:

class Foo: Parent {
    var children = [Foo]()
}

let anything: Any = Foo()

// use `if let` and `as?` instead of `is` in order to have a more static type
if let aDynamicParent = anything as? _Parent {
    aDynamicParent.anyChildren.map{ $0 as! Foo } // cast the array back to its original type

    aDynamicParent.children = [Foo(), Foo(), Foo()]
}
+4

Child Parent typealiases, Parent , Child, Child Parent.

protocol Parent {
    var children: [Child] { get set }
}

protocol Child {
    var parent: Parent { get nonmutating set }
}

class Foo: Parent {
    var children: [Child]
    init(children: [Child]) {
        self.children = children
        self.children.forEach { $0.parent = self }
    }
}

class Bar: Child {
    var parent: Parent
    init(parent: Parent) {
        self.parent = parent
        self.parent.children.append(self)
    }
}

let testVar = Foo(children: [Bar]())
let cVar = Bar(parent: testVar)

let parent = testVar as Parent 
let children = parent.children
0

Source: https://habr.com/ru/post/1606616/


All Articles