0

I write a custom storage, that should supports only objects that conform some protocol:

protocol MyBaseProtocol {
    func baseMethod()
}
class Stor <ElementType : MyBaseProtocol>  {
    var storage = [ElementType]()
    
    func addElement(_ element: ElementType) {
        storage.append(element)
    }
}

Next I've created a child protocol and want to store only objects what conform the child protocol:

protocol MyProtocol : MyBaseProtocol {
    func method()
}
var otherStorage = Stor<MyProtocol>() //compilation error
class C1 : MyProtocol {
    func method() {
    }
    func baseMethod() {
    }
}
class S1 : MyProtocol {
    func method() {
    }
    func baseMethod() {
    }
}
otherStorage.addElement(C1())
otherStorage.addElement(S1())

I've got an error:

Value of protocol type 'MyProtocol' cannot conform to 'MyBaseProtocol'; only struct/enum/class types can conform to protocols

How I can create an instance of Stor that can store only objects that conform MyBaseProtocol?

Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
Andrew Romanov
  • 4,774
  • 3
  • 25
  • 40

1 Answers1

0

You are running into the issue of protocols not conforming to themselves. You can resolve this by creating a concrete type conforming to MyProtocol and converting all your conforming types to that before storing them in your Store.

class AnyMyProtocol: MyProtocol {
    private let _baseMethod: () -> ()
    private let _method: () -> ()

    init(base: MyProtocol) {
        _baseMethod = base.baseMethod
        _method = base.method
    }

    func baseMethod() {
        _baseMethod()
    }

    func method() {
        _method()
    }
}

extension MyProtocol {
    var erased: AnyMyProtocol {
        AnyMyProtocol(base: self)
    }
}

var otherStorage = Store<AnyMyProtocol>()

class C1 : MyProtocol {
    func method() {}
    func baseMethod() {}
}

struct S1 : MyProtocol {
    func method() {}
    func baseMethod() {}
}

enum MyEnum: MyProtocol {
    case some

    func method() {}
    func baseMethod() {}
}

otherStorage.addElement(C1().erased)
otherStorage.addElement(S1().erased)
otherStorage.addElement(MyEnum.some.erased)
Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
  • I need use any types of objects in same Array (Enums, Classes, Structs). And have some base class is not good option for my goals. – Andrew Romanov Jul 06 '20 at 08:47
  • @AndrewRomanov you can use any type with the type erased `AnyMyProtocol` I've created (be it an enum, struct or class). If this doesn't suit your needs, you'll need to rethink your requirements and implementation of `Store`, because there's no other way to resolve your protocol problem. – Dávid Pásztor Jul 06 '20 at 08:49
  • @AndrewRomanov updated with answer with storing a `struct` and an `enum` in `Store` as well – Dávid Pásztor Jul 06 '20 at 08:51