考虑这个Person
类,它只是实现StringLiteralConvertible
并将字符串文字分配给name
:
class Person : StringLiteralConvertible {
var name : String?
typealias StringLiteralType = String
required init(stringLiteral value: StringLiteralType) {
println("stringLiteral \(value)")
name = value
}
typealias ExtendedGraphemeClusterLiteralType = String
required init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) {
println("extendedGraphemeClusterLiteral \(value)")
name = value
}
typealias UnicodeScalarLiteralType = Character
required init(unicodeScalarLiteral value: UnicodeScalarLiteralType) {
println("unicodeScalarLiteral \(value)")
name = "\(value)"
}
}
这允许我使用字符串创建Person
实例:
let aaron : Person = "Aaron"
我甚至可以从字符串数组中转换Person
s数组:
let names = ["John", "Jane"] as [Person]
但是这仅适用于字符串文字。如果我使用字符串变量,它将失败:
let aaronString = "Aaron"
let aaron : Person = aaronString
// Error: 'NSString' is not a subtype of 'Person'
类似地,尝试强制转换非文字字符串数组失败:
let nameStrings = ["John", "Jane"]
let people : [Person] = nameStrings
// Error: 'String' is not identical to 'Person'
我有三个问题:
我可以实现另一个协议来将非文字字符串转换为Person
吗?我想这样做,所以我可以转换整个集合来转换对象。
如果不是#1,map +初始化程序是自己执行转换的最佳方式吗?
let nameStrings = ["John", "Jane"]
let people = nameStrings.map{Person(name: $0)}
如果是#1,是否有类似的方法可用于指定转换两个在层次结构中无关的对象的方法?也就是说,如果没有初始化程序,我可以解决此错误吗?
let rikerPerson : Person = "Riker"
let rikerEmployee = rikerPerson as Employee
// Error: 'Person' is not convertible to 'Employee'
答案 0 :(得分:3)
你所描述的“铸造”并不是真正的铸造(比如,s = “fred”; ns = s as NSString
,或者是用C ++铸造的)。
let names = ["John", "Jane"] as [Person]
只是另一种写作方式:
let names: [Person] = ["John", "Jane"]
即告诉Swift使用StringLiteralConvertible
的许多可能版本中的哪一个(而不是String
的版本,这是默认值)。
换句话说 - 您的as
正在履行与此代码段中as
类似的功能,该功能消除了两个仅因返回类型而不同的重载函数的歧义:
func f() -> String { return "foo" }
func f() -> Int { return 42 }
let i = f() as Int // i will be 42
let s = f() as String // s will be “foo"
此处没有“转化” - as
仅用于消除哪些f
Swift电话的歧义。与选择init(stringLiteral:)
的情况相同。
绝对(但只有在map
和{ }
之间放置一个空格;-)。
如果您担心将所有内容转换为数组的浪费只是为了做其他事情,请查看lazy(a).map
不。在测试版中,曾经有一个__conversion() -> T
方法可以在你自己的类上实现这样的“强制转换” - 或者更重要的是,允许你将Person
类传递给一个函数一个Employee
参数,并将其隐式转换。但那消失了。一般来说,这种隐式转换与Swift的风格是对立的,除了在极少数情况下(Obj-C和C interop,以及选择性中的隐式包装,是主要的)。您必须为init
写一个Employee
,其中Person
(或Person
符合的某个类或协议),然后调用它。