Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
181 views
in Technique[技术] by (71.8m points)

ios - Cannot assign class instance to its protocol type?

Please see self containing example below. Compiler reports an error on the last line (marked by COMPILE ERROR) where I am assigning an instance of SimpleTrain to a protocol type that it (in my best judgement) conforms to. How can I make it compile? What am I doing wrong? Or is this compiler issue?

protocol Train {
    typealias CarriageType

    func addCarriage(carriage: CarriageType)
    func shortTrain<ShortType: Train where ShortType.CarriageType == CarriageType>() -> ShortType
}

class SimpleTrain<T> : Train {
    typealias CarriageType = T
    private var carriages: [T] = [T]()

    func addCarriage(carriage: T) {
       carriages.append(carriage)
    }

    func shortTrain<ShortType: Train where ShortType.CarriageType == CarriageType>() -> ShortType {
        let short = SimpleTrain<T>()
        short.addCarriage(carriages[0])
        return short //COMPILE ERROR: SimpleTrain<T> is not convertible to 'ShortType'
    }
}

EDIT: Even when I explicitly downcast the shortTrain's return type above (so that last line of code snippet above reads return short as ShortType) as suggested by Antonio there is still compilation error when calling function shortTrain:

let s = SimpleTrain<String>()
s.addCarriage("Carriage 1")
s.addCarriage("Carriage 2")

let a = s.shortTrain() //ERROR: Cannot convert the expression's type '()' to type 'Train'
let b = s.shortTrain<SimpleTrain<String>>() //ERROR: cannot explicitly specialize a generic function
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

An explicit downcast of either the variable:

let short = SimpleTrain<T>() as ShortType

or the return value:

return short as ShortType

solves the problem.

Update

When I was answering to the question, I wondered myself how the Train protocol can be used as a return type, being it typealiased.

Look at this code:

protocol ProtocolWithNoAlias {        
}

protocol ProtocolWithAlias {
    typealias AliasType
}

var x: ProtocolWithNoAlias?
var y: ProtocolWithAlias?

The last line is reported as a compilation error:

Protocol 'ProtocolWithAlias' can only be used as a generic constraint because it has Self os associated type requirements

which means you cannot use ProtocolWithAlias as a concrete type, which in turn means you cannot declare variables having ProtocolWithAlias type, and consequently it doesn't make sense to define function returning it.

I cannot find any mention about that in the official documentation, but I am sure I read somewhere, I just don't remember where.

Conclusion: I interpret the error you're having troubles with:

SimpleTrain<T> is not convertible to 'ShortType'

as a direct consequence of the protocol being typealiased.

Note that this is my personal opinion, since I am unable at this moment to prove it besides that code snippet testing protocol with and without aliases.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...