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是一个类名,它也是一个协议名称
#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
答案 0 :(得分:5)
Objective-C和Swift有不同的名称解析方案,导致这种情况发生。
Foo
的类由裸标识符Foo
引用,而名为Foo
的协议由@protocol(Foo)
。这里没有冲突。Foo
的类和名为Foo
的协议之间的语法没有区别,部分导致上述错误。< / LI>
醇>
请注意,由于Swift中名称解析的方式,enum
s / struct
s / class
es 可以与协议具有相同的名称,并且反之亦然;名称本身在Swift中不是唯一的,但完全限定的名称是。您收到上述错误的原因实际上是因为struct Test
和protocol Test
都具有相同的完全限定名称:<name-of-your-module>.Test
但是,没有什么可以阻止您在不同的模块中声明struct Test
和protocol Test
,因为它们具有不同的完全限定名称。例如,欢迎您添加
struct ExpressibleByStringLiteral {}
到您的代码,尽管标准库提供了该名称的协议。 ExpressibleByStringLiteral
会影响标识符的其他用法,因此要引用stdlib提供的协议,您需要使用完全限定名称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中的所有类型都是如此 - 只要完全限定名称是唯一的,多个类型可以具有相同的名称。
答案 1 :(得分:0)
编译器可以根据上下文区分协议名称和类名称。因此,如果您知道将其用作协议以及将其用作类,就不会有歧义。
比方说,我们有一个符合Car
协议的Car
类。
@protocol Car <NSObject>
- (BOOL)canRun;
@end
@interface Car : NSObject <Car>
@end
@implementation Car
- (NSString *)description {
return [NSString stringWithFormat:@"im a car"];
}
- (BOOL)canRun {
return YES;
}
@end
您可以使用Car
作为协议,编译器会知道。
/* compiler tasks Car as a protocol*/
// 1
id<Car> car;
// 2
[obj comformsToProtocol: @protocol(Car)];
// 3
@interface Truck : NSObject <Car>
@end
// 4
@protocol AnotherProtocol <Car>
@end
您还可以将Car
用作类,编译器也将知道它。
/* compiler tasks Car as a class*/
// 1
Car *car = [Car new];
// 2
[Car someClassMethod];
// 3
@interface Truck : Car
@end