arrays - Swift: crear una matriz con un valor predeterminado de instancias de objeto distintas
initialization instance (1)
Las clases son tipos de referencia, por lo tanto, como notó, todos los elementos de la matriz en
var users = [User](count: howManyUsers, repeatedValue:User(thinkTime: 10.0))
haga referencia a la misma instancia de objeto (que se crea primero y luego se pasa como argumento al inicializador de matriz).
Para un tipo de
struct
obtendría un resultado diferente.
Una posible solución:
var users = (0 ..< howManyUsers).map { _ in User(thinkTime: 10.0) }
Aquí, se crea una instancia de
User
para cada uno de los índices de la matriz.
Si lo necesita con frecuencia, puede definir un método de inicio de matriz que tome un parámetro de "cierre automático":
extension Array {
public init(count: Int, @autoclosure elementCreator: () -> Element) {
self = (0 ..< count).map { _ in elementCreator() }
}
}
var users = Array(count: howManyUsers, elementCreator: User(thinkTime: 10.0) )
Ahora el segundo argumento
User(thinkTime: 10.0)
lo envuelve el compilador en un cierre, y el cierre se ejecuta para cada índice de matriz.
Actualización para Swift 3:
extension Array {
public init(count: Int, elementCreator: @autoclosure () -> Element) {
self = (0 ..< count).map { _ in elementCreator() }
}
}
Noté un comportamiento un tanto extraño ( y peligroso en mi humilde opinión ) al crear una matriz con un valor predeterminado . Como se indica en Swift 2.1: Tipos de colección
El tipo de matriz de Swift también proporciona un inicializador para crear una matriz de cierto tamaño con todos sus valores establecidos en el mismo valor predeterminado. Le pasa a este inicializador el número de elementos que se agregarán a la nueva matriz (llamado conteo) y un valor predeterminado del tipo apropiado (llamado valor repetido):
El punto es: el mismo valor predeterminado ; Para entender cómo funciona, intenté crear una matriz de elementos de esta clase de ejemplo
class User {
private struct Shared {
static var sequence: Int = 0
}
var id: Int
var thinkTime: NSTimeInterval // typealias di Double
init (thinkTime: NSTimeInterval) {
User.Shared.sequence = User.Shared.sequence+1
id = User.Shared.sequence
self.thinkTime = thinkTime
}
}
y este código de prueba:
let howManyUsers: Int = 3
var users = [User](count: howManyUsers, repeatedValue:User(thinkTime: 10.0))
let u2: User = User(thinkTime: 10)
let u3: User = User(thinkTime: 10)
users.append(u2)
users.append(u3)
users[1].thinkTime = 20
users[3].thinkTime = 30
for u in users {
print("User id:/(u.id) thinktime:/(u.thinkTime)")
}
da:
User id:1 thinktime:20.0
User id:1 thinktime:20.0
User id:1 thinktime:20.0
User id:2 thinktime:30.0
User id:3 thinktime:10.0
que prueban definitivamente el inicializador con el número de elementos que se agregarán a la nueva matriz y un valor predeterminado del tipo apropiado son: la misma instancia de objeto
¿Cuál es la forma, lo más concisa e inteligente posible, de obtener una matriz de instancias de objeto distintas , instaladas con el mismo valor predeterminado (no la misma instancia, sino varias instancias inicializadas con el mismo valor predeterminado)?