2017-01-22 12 views
1

Мне было интересно, есть ли конструкция на языке программирования Swift 3, которая позволяет мне хранить некоторые объекты в массиве, но инициализировать каждый элемент в этом массиве лениво.Array с ленивыми элементами

Представьте себе этот пример класса:

class A { 
    let test = "hello" 
    let test2 = 2.0 
} 

Теперь я хочу, чтобы хранить массив объектов «A» в массиве другого класса, например:

class B { 
    var lazy(?) array: [A] = { 
     // Some code to initialize the element being accessed 
    }() 
} 

Если я получить доступ к любому элементу Теперь, было бы здорово, если бы он инициализируется только тогда, когда я к нему доступ, так лениво

print(B.array[1].test) (element at index one is now initialized) 

является ли это ПОСС кий?

+0

Я не k теперь достаточно, чтобы ответить, но я верю, что вы ищете протокол «Генератор» или что-то вроде этого. Здесь вы идете ... http://nshipster.com/swift-collection-protocols/ – Fogmeister

ответ

2

Вы можете использовать для хранения в lazy подкладочный для A, который инициализируется в первом доступе, например:

class Astorage { 
    /* ... lots of ... */ 
    let id: Int 
    var foo: String = "bar" 
    init(_ id: Int) { 
     self.id = id 
     print("Initializing backing storage for A with id \(id)") 
     // ... 
    } 
} 

class A { 
    private let id: Int 
    lazy var storage: Astorage = Astorage(self.id) 
    init(_ id: Int) { 
     self.id = id 
    } 
} 

class B { 
    var array: [A] 
    init (_ array: [A]) { 
     self.array = array 
    } 
} 

let b = B((1...5).map(A.init)) 

b.array[2].storage.foo = "foo" 
// Initializing backing storage for A with id 3 

b.array[4].storage.foo = "bax" 
// Initializing backing storage for A with id 5 
+1

фантастический, именно то, что я искал! –

2

Вы можете использовать enum и mutatingstruct для этого

enum LazyValueEnum<T>: CustomStringConvertible { 
    case value(T) 
    case thunk((Void) -> T) 

    var forceValue: T { 
     switch self { 
     case .value(let t): 
       return t 
     case .thunk(let thunk): 
       return thunk() 
     } 
    } 

    var description: String { 
     switch self { 
     case .value(let t): 
      return String(describing: t) 
     case .thunk(_): 
      return "<thunk>" 
     } 
    } 
} 

struct LazyValue<T>: CustomStringConvertible { 

    var value: LazyValueEnum<T> 

    init(_ t: T) { 
     self.value = .value(t) 
    } 

    init(lazy thunk: @escaping (Void) -> T) { 
     self.value = .thunk(thunk) 
    } 

    static func lazy(_ thunk: @escaping (Void) -> T) -> LazyValue<T> { 
     return LazyValue(lazy: thunk) 
    } 

    static func value(_ value: T) -> LazyValue<T> { 
     return LazyValue(value) 
    } 

    mutating func forceValue() -> T { 
     let t = value.forceValue 
     value = .value(t) 
     return t 
    } 

    var description: String { 
     return value.description 
    } 
} 


var a: [LazyValue<Int>] = [.value(5), .value(7), .lazy { Int(arc4random()) }] 
print(a) 
print(a[2].forceValue()) 
print(a) 
print(a[2].forceValue()) 
print(a) 

Результаты от детская площадка: enter image description here

+0

также работает, но я нахожу ответ dfri более понятным и понятным для понимания –

 Смежные вопросы

  • Нет связанных вопросов^_^