在Array扩展中创建泛型函数时,我发现了这个模糊的问题。让我们说我有用于创建数组的用户类:
class User : NSObject {
let name : String
let surname : String
init(name : String, surname : String) {
self.name = name
self.surname = surname
}
override var description : String {
return self.name + " " + self.surname
}
}
请注意,我需要它作为NSObject的子类。现在让我们创建两个用户并将其添加到用户数组中。
var user1 = User(name: "Jimmy", surname: "Page")
var user2 = User(name: "David", surname: "Guilmour")
var users = Array<User>()
users.append(user1)
users.append(user2)
现在我需要一个具有特定于Array的函数的Array扩展,或者User的任何其他子类,它将向一些用户数组添加一些测试用户。我在扩展名中写的原因而不是我自己的类型是因为我想使用if let something = something as [User]
来检查它的类型。如果我建立自己的类型,我将无法做到这一点。
extension Array {
mutating func addTestUsers<T : User>() {
var testUser1 = User(name: "King", surname: "Brown")
var testUser2 = User(name: "Carlos", surname: "Santana")
self.append(testUser1)
self.append(testUser2)
}
}
当使用追加函数或任何其他可能以某种方式改变初始数组的函数时,会出现问题。
错误:Cannot invoke append with argument list of type (User)
我知道这是因为扩展永远不会被指定为用户数组的扩展,但正如我所看到的,我无法做到这一点。
答案 0 :(得分:0)
正如@Martin R的评论中所建议的那样,如果你看一下Array extension to remove object by value,那么最高的投票回答建议写一个以数组为参数的函数,在你的情况下你可以这样做:
func addTestUsers(inout array: [User]) {
let user1 = User(name: "King", surname: "Brown")
let user2 = User(name: "Carlos", surname: "Santana")
array += [user1, user2]
}
然后您可以像这样使用它:
var array = [User(name: "Jimmy", surname: "Page")]
addTestUsers(&array) // [Jimmy Page, King Brown, Carlos Santana]
但是,如果您打算创建User
的子类,则之前的方法是不合适的,因为您将无法传递子类数组作为参数。在这种情况下,您可以覆盖addTestUsers
以接受您的子类,但更优雅的解决方案可能是:
func addTestUsers<T: User>(inout array: [T]) {
let user1 = T(name: "King", surname: "Brown")
let user2 = T(name: "Carlos", surname: "Santana")
array += [user1, user2]
}
要使上一个功能正常工作,您需要将init(name : String, surname : String)
中的User
标记为required
:
class User : NSObject {
// ...
required init(name : String, surname : String) {
self.name = name
self.surname = surname
}
// ...
}
将其标记为required
表示User
的任何子类必须实施init(name : String, surname : String)
,因此在T(name: "...", surname: "...")
中使用addTestUsers
是安全的}。