2
protocol Nameable: Equatable {
    var name: String { get set }
}

struct Person: Nameable {
    var name: String
}

struct Car: Nameable {
    var name: String
}

Now I can constrain a function to be able to print elements conforming to the Nameable protocol since they are of the same type?

func printNameable<T: Nameable>(_ list: [T]) {

}

But how I can create this list? I get a syntax Error.

var nameableList<T: Nameable>: [T] = []

Or if I try next I get Protocol 'Nameable' can only be used as a generic constraint ...

var nameables: [Nameable] = []

I am forced to specify a Nameable type like Person or Car to create this list?

Basically, in the end, I want an array of a common protocol that can have a variety of different type objects that I can compare, if they are of different type they are different, but if not, I want to compare them.

var nameables: [Nameable] = [Person(name: "John"), Car(name: "Ferrari")]

nameables.contains(Car(name: "Ferrari")) 

(I guess both types, Person and Car should conform Equatable protocol).

Paulw11
  • 108,386
  • 14
  • 159
  • 186
Godfather
  • 4,040
  • 6
  • 43
  • 70
  • 4
    This is because your `Namable` protocol extends `Equatable` protocol and `Equatable` has `func ==(lhs: Self, rhs: Self) -> Bool` And a protocol that contains Self somewhere inside it cannot be used anywhere except in a type constraint. copied from : https://stackoverflow.com/questions/24926310/what-does-protocol-can-only-be-used-as-a-generic-constraint-because-it-has – Sandeep Bhandari Feb 27 '19 at 08:25
  • [This answer](https://stackoverflow.com/a/36350283/219971) has a detailed explanation with a reference for deeper dive into understanding this implementation. – Swapnil Luktuke Feb 28 '19 at 07:05

1 Answers1

1

You can't actually pass printNameable<T>(_:) an array that contains both Car and Person objects, it can only contain one or the other. The generic type T isn't a runtime value, it's calculated at compile time, so if your code calls printNameable(persons) and printNameable(cars) you will actually have 2 different compiled functions (someone correct me if I'm wrong).

As @Sandeep Bhandari mentioned in their comment, since your protocol extends Equatable, which contains Self, your protocol can only be used as a generic constraint. If you want your protocol to be usable in the way that you want just remove Equatable and then change printNameable(_:) to

func printNameable(_ list: [Nameable]) {
}
Guy Kogus
  • 7,251
  • 1
  • 27
  • 32