Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

protocol with same associated type name

If I have two protocols whose associated type happens to be the same, such as

protocol Read {
    associatedtype Element
    func read() -> Element
}
protocol Write {
    associatedtype Element
    func write(a: Element)
}

Then I would like to have a class to read integer from and write string to:

class ReadWrite: Read, Write {
    func read() -> Int {
        return 5
    }
    func write(a: String) {
        print("writing \(a)")
    }
}

but the compiler complains and suggests changing String to Int. Ideally the type should be inferred, or at least compiles if I explicitly declare

associatedtype Read.Element = Int
associatedtype Write.Element = String

within ReadWrite. Any work around?

update

Workaround inspired by this question is to create two auxiliary protocols

protocol ReadInt: Read {
    associatedtype Element = Int
}
protocol WriteString: Write {
    associatedtype Element = String
}

and have the class inherit from these two instead:

class ReadWrite: ReadInt, WriteString {
    func read() -> Int {
        return 5
    }
    func write(a: String) {
        print("writing \(a)")
    }
}

This seems to compile, but I am afraid of any gotcha following this way.

update again

I found the issue in Swift's issue tracker. Anyone require this missing feature (like me) should vote for it. As a comparison, this pattern is possible in Rust, which also supports associated types (although this is not an idiomatic usage).

like image 488
Franklin Yu Avatar asked Nov 08 '22 13:11

Franklin Yu


1 Answers

Another workaround is to create a third, combined protocol:

protocol ReadWrite {
    associatedtype R
    associatedtype W
    func read() -> R
    func write(a: W)
}

It's not pretty, since it forces you to redeclare the protocol members, but it does keep it generic (you're not limited to String and Int).

like image 197
Mike Taverne Avatar answered Nov 15 '22 06:11

Mike Taverne