正常情况下,struct
的用法是这样的:
struct Person {
var name: String
var age: Int
}
let person = Person(name: "Ken", age: 3)
print(person.name)
如果把Person
的定义放到一个叫People
的Framework
中去,然后在调用的地方加上import
语句来引用
import People
这样会报错:
Use of unresolved identifier 'Person'
因为Framework
里的定义要声明为public
才能给外部使用。如下:
public struct Person {
var name: String
var age: Int
}
但这样还是会报错:
'Person' cannot be constructed because it has no accessible initializers
因为一般情况下,struct
在没有自定义init
时,会自动生成一个全部成员的init
,如下:
init(name: String, age: Int) {
self.name = name
self.age = age
}
但是一放到Framework
中,怎么又提示"no accessible initializers"呢?
请看官方文档的描述:
"Default Memberwise Initializers for Structure Types The default memberwise initializer for a structure type is considered private if any of the structure’s stored properties are private. Otherwise, the initializer has an access level of internal.
As with the default initializer above, if you want a public structure type to be initializable with a memberwise initializer when used in another module, you must provide a public memberwise initializer yourself as part of the type’s definition."
也就是说这个自动生成的init
的access level默认情况下是internal
(如果有任何成员是private
,则它也会降为private
)。而像前面提到过的,标记为public
的定义才能被Framework
外部访问。所以自己写一个public
的init
就好了。
不太理解为什么要这样设计,明白的同学还请指教。
代码变成这样:
public struct Person {
var name: String
var age: Int
public init(name: String, age: Int) {
self.name = name
self.age = age
}
}
let person = Person(name: "Ken", age: 11)
print(person.name)
但这样依然会报错:
Value of type 'Person' has no member 'name'
这是因为上面的Person
虽然定义成了public
,但成员还是internal
的,要访问必须加上public
。这个设计虽然稍显啰嗦,但还是比较严谨的。
最终代码:
public struct Person {
public var name: String
public var age: Int
public init(name: String, age: Int) {
self.name = name
self.age = age
}
}
let person = Person(name: "Ken", age: 11)
print(person.name)
参考:
How can I make public by default the member-wise initialiser for structs in Swift?
网友评论