Swift,无法编译,编译器会直接报错。
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,可以编译成功,比如NSObject是类名,也是协议(protocol)名
#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
最佳答案
Objective-C 和 Swift 具有不同的名称解析方案,这导致了这种情况的发生。
- 在 Objective-C 中,类名和协议(protocol)名通常是唯一的。 (您始终可以注册一个与现有协议(protocol)或类同名的新协议(protocol)或类,但您通常会收到警告,并且事情肯定会表现得很奇怪。)但是,类名和协议(protocol)名存在于不同的 namespace 中——类名可以隐藏协议(protocol)名称,反之亦然。这通常没问题,因为类和协议(protocol)在源代码中的引用方式不同:名为
Foo
的类由裸标识符引用Foo
, 而一个名为Foo
的协议(protocol)由@protocol(Foo)
引用.这里没有冲突。 - 然而,在 Swift 中,不同类型之间的名称解析没有区别。协议(protocol)名称与所有其他类型名称位于同一命名空间中,引用名为
Foo
的类在语法上没有区别。和一个名为Foo
的协议(protocol),部分导致上述错误。
请注意,由于 Swift 中的名称解析方式,enum
s/struct
s/class
es 可以与协议(protocol)同名,反之亦然;名称本身在 Swift 中不是唯一的,但完全限定的名称是。你得到上面错误的原因实际上是因为 struct Test
和 protocol Test
将具有相同的完全限定名称:<name-of-your-module>.Test
没有什么可以阻止您声明 struct Test
和 protocol Test
但是,在不同 模块中,因为它们具有不同的完全限定名称。例如,欢迎您添加
struct ExpressibleByStringLiteral {}
到你的代码,尽管标准库提供了一个同名的协议(protocol)。 ExpressibleByStringLiteral
然后会隐藏标识符的其他用法,因此要引用 stdlib 提供的协议(protocol),您需要使用 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
这对 Swift 中的所有类型都是如此 — 多个类型可以具有相同的名称,只要它们的完全限定名称是唯一的即可。
关于objective-c - 为什么Objective-C类和协议(protocol)可以重名,而Swift不可以,语言实现有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49221554/