LombaX
LombaX

Reputation: 17364

Generics on protocol

I have this protocol:

protocol Addable
{
    mutating func addNumber(value: Int)
}

and this extension

extension Int : Addable
{
    mutating func addNumber(value: Int)
    {
        self = self + value
    }
}

This code:

    var number : Int = 10
    number.addNumber(10)
    println(number)

Correctly prints 20

Now I want to extend the protocol Addable to other types. If I understand correctly, I don't use Generics with protocol, but I use an associated type:

protocol Addable
{
    typealias AddableType
    mutating func addNumber(value: AddableType)
}

So now, AddableType means a generic type, and I can extend for example Float

extension Float : Addable
{
    mutating func addNumber(value: Float)
    {
        self = self + value
    }
}

    var another : Float = 10.5
    another.addNumber(10.1)
    println(another)

This prints 20.6

Now, I know that I can enforce the associated type to conform to a protocol

protocol Addable
{
    typealias AddableType : AProtocol, AnotherProtocol // ...
    mutating func addNumber(value: AddableType)
}

But, and here it's the question, I cannot enforce the conformance to a Type or some types

protocol Addable
{
    typealias AddableType : Int, Float
    mutating func addNumber(value: AddableType)
}

Error: Inheritance from non-protocol, non-class type 'Int'
Error: Inheritance from non-protocol, non-class type 'Float'

Is there any possibility to do this?

Upvotes: 2

Views: 339

Answers (3)

Sean
Sean

Reputation: 370

Types can conform to protocols, and protocols can conform to protocols, but protocols cannot conform to types. Having a protocol conform to a type doesn't make any sense within the grammatical definition of the language.

I'm guessing that your intention is to limit the types of objects that are allowed to conform to this protocol. In that case, you can define a protocol that inherits from a type, and then have your protocol conform to that protocol.

protocol TypeRestrictor {}

extension Int: TypeRestrictor {}
extension Float: TypeRestrictor {}

protocol Addable {
    typealias AddableType: TypeRestrictor
    mutating func addNumber(value: AddableType)
}

Upvotes: 2

nickgraef
nickgraef

Reputation: 2417

You could define a new protocol and declare conformance for the types you want to allow.

protocol AllowedAddableType {}

extension Int: AllowedAddableType {}
extension Float: AllowedAddableType {}
// ...

protocol Addable
{
    typealias AddableType: AllowedAddableType
    mutating func addNumber(value: AddableType)
}

Upvotes: 2

drewag
drewag

Reputation: 94683

You can create a second protocol and implement that on the types that you want:

protocol AddableRequirement {}

extension Int: AddableRequirement {}
extension Float: AddableRequirement {}

protocol Addable {
    typealias AddableType: AddableRequirement
    mutating func addNumber(value: AddableType)
}

You also may want to use Self instead of a typealias:

protocol Addable {
    mutating func addNumber(value: Self)
}

That way, your protocol requires that the type always be addable with itself.

Upvotes: 3

Related Questions