Why does Objective-C class and protocol can have the same name, but Swift can't, what's the difference in language implementation?
Objective-C and Swift have different name resolution schemes which cause this to happen.
- In Objective-C, class and protocol names are generally unique. (You can always register a new protocol or class with the same name as an existing one, but you'll generally get a warning and things are guaranteed to behave strangely.) However, class names and protocol names exist in different namespaces — class names can shadow protocol names, and vice versa. This is generally okay because classes and protocols are referred to differently in source code: a class named
Foo
is referred to by the bare identifierFoo
, while a protocol namedFoo
is referred to by@protocol(Foo)
. There's no clashing here. - In Swift, however, there is no difference in the name resolution between different types. Protocol names are in the same namespace as all other type names, and there is no difference in the syntax between referring to a class named
Foo
and a protocol namedFoo
, partially leading to the error above.
Note that because of how name resolution happens in Swift, enum
s/struct
s/class
es can have the same names as protocols, and vice versa; names themselves are not unique in Swift, but fully-qualified names are. The reason you get the error above is actually because both struct Test
and protocol Test
would have the same fully-qualified name: <name-of-your-module>.Test
There is nothing preventing you from declaring struct Test
and protocol Test
in different modules, though, since they'd have different fully-qualified names. For instance, you're welcome to add
struct ExpressibleByStringLiteral {}
to your code, despite a protocol by that name being offered by the standard library. ExpressibleByStringLiteral
would then shadow other usages of the identifier, so to refer to the protocol provided by the stdlib, you'd need to use the fully-qualified name of Swift.ExpressibleByStringLiteral
:
struct ExpressibleByStringLiteral {}
struct S1 : ExpressibleByStringLiteral {} // error: inheritance from non-protocol type 'ExpressibleByStringLiteral'
struct S2 : Swift.ExpressiblyByStringLiteral {} // need to add methods to satisfy the protocol
This is true for all types in Swift — multiple types can have the same name as long as their fully-qualified names are unique.