Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Objective-C class and protocol can have the same name, but Swift can't, what's the difference in language implementation?

Swift, Can't compile, compiler will directly report error.

protocol Test {}

struct Test {}


// Swift compile output:

// Untitled.swift:4:8: error: invalid redeclaration of 'Test' struct Test {}

// Untitled.swift:2:10: note: 'Test' previously declared here protocol Test {}

Objective-C, Can be compiled successfully, for example NSObject is a class name, it is also a protocol name

#import <Foundation/Foundation.h>

@protocol Test
@end

@interface Test
@end

int main(int argc, char *argv[]) {
    @autoreleasepool {
        NSLog(@"Hello word");
    }
}
// Objective-C output
// 2018-03-11 23:14:20.341 Untitled[34921:1272761] Hello word
like image 953
TBXark VFanx Avatar asked Mar 11 '18 15:03

TBXark VFanx


People also ask

What is difference between Objective-C protocol and Swift protocol?

In Objective-C, protocols are declared with the “@protocol” keyword. Below is an example of declaring a protocol containing one required method. In Swift, the syntax is a little different but the idea is the same. In Objective-C, you add the protocol name in angle brackets beside the class interface declaration.

Can Swift protocol be used in Objective-C?

You can work with types declared in Swift from within the Objective-C code in your project by importing an Xcode-generated header file. This file is an Objective-C header that declares the Swift interfaces in your target, and you can think of it as an umbrella header for your Swift code.

Why Swift is called protocol based language?

Swift checks for protocol conformity issues at compile-time, allowing developers to discover some fatal bugs in the code even before running the program. Protocols allow developers to write flexible and extensible code in Swift without having to compromise the language's expressiveness.

What is difference between protocol and delegate in Swift?

Protocol is a set of methods (either optional or required) that would be implemented by the class which conforms to that protocol. While, delegate is the reference to that class which conforms to that protocol and will adhere to implement methods defined in protocol.


1 Answers

Objective-C and Swift have different name resolution schemes which cause this to happen.

  1. 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 identifier Foo, while a protocol named Foo is referred to by @protocol(Foo). There's no clashing here.
  2. 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 named Foo, partially leading to the error above.

Note that because of how name resolution happens in Swift, enums/structs/classes 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.

like image 119
Itai Ferber Avatar answered Sep 28 '22 08:09

Itai Ferber