2
votes

I've tried to use generic type with protocol:

class Weak<T: AnyObject> {
    weak var value: AnyObject?
    init (value: AnyObject) {
        self.value = value
    }
}

protocol SomeProtocol: AnyObject {
    func doSomething()
}

func createWeak(object: SomeProtocol) -> Weak<SomeProtocol> {
    return Weak<SomeProtocol>(value: object)
}

class SomeClass: SomeProtocol {
    func doSomething() {
        print("Some 2")
    }
}

let temp =  SomeClass()
let weakObject = createWeak(object: temp)
weakObject.value?.doSomething()

And got the compiler error: error: 'SomeProtocol' is not convertible to 'AnyObject' return Weak(value: object)

But without AnyObject constraint it works fine

class Weak<T> {
var value: T?
    init (value: T) {
        self.value = value
    }
}

protocol Protocol {
    func doSomething()
}

class Class: Protocol {
    func doSomething() {
        print("This is class")
    }
}

func createWeak(object: Protocol) -> Weak<Protocol> {
    return Weak(value: object)
}

let temp =  Class()
let weakObject = createWeak(object: temp)
weakObject.value?.doSomething()

Why I can't use protocols inherited form AnyObject in generic classes?

1
This great answer might help you: stackoverflow.com/a/43408193/1974224Cristik
"I've tried to use generic type with protocol." And that was your first mistake. :D But quite seriously, it is very tricky to mix generics and protocols, and it is rarely worth the complexity. As @Cristik notes, your approach will not work in Swift.Rob Napier
It's worth noting that your Weak doesn't make sense as written. You're not using T. What I think you meant was weak var value: T? and init(value: T). This won't help your underlying problem. As Cristik notes, this entire approach is not possible. You cannot create Weak<SomeProtocol>. The type must be concrete, not a protocol.Rob Napier

1 Answers

3
votes

Swift protocols are incomplete types, which means that you can't use them in places like generic arguments, as the compiler needs to know the whole type details so it can allocate the proper memory layout.

Your createWeak function can still be used if you make it generic:

func createWeak<T: SomeProtocol>(object: T) -> Weak<T> {
    return Weak<T>(value: object)
}

The above code works because the compiler will generate at compile time a function mapped to the concrete type you pass.

Even better, you can make the initializer generic, and convert Weak to a struct (value types are preferred Swift over reference ones):

struct Weak<T: AnyObject> {
    weak var value: T?

    init(_ value: T) {
        self.value = value
    }
}

which you can use it instead of the free function:

let weakRef = Weak(temp)