Reputation: 12446
I have an initializer, it needs one value.
internal init(value pValue: T) { ... }
Now I have a convenience initializer, to convert an array to my type. But that array may not be empty (because it needs a value to make sense, therefore there is the designated initializer ahead).
internal convenience init(array pArray: [T]) {
guard !pArray.isEmpty else {
// it is not correct to init without at least one value
return // or assert
} // compiler error because there is no init call
.. // init with non-empty array
}
What would be the a solution to this, so that someone who uses the interface wouldn't be surprised and still had good usability?
The hurdle here is, that in an initializer, every path need to call an initializer.
The solution, I think would make sense is, when the initializer gets an empty array as an argument, is to create the type with an arbitrary value of that type T
.
self.init(T())
But I can not create T
, because I do not know the initializers for T
.
And I can not simply use
self.init(0)
because the compiler wants an initializer with type T
.
I did implement it as a static method and it works (because I can just opt out to use init), but I want it as a non static method
I also did implement it as an variadic parameter and it works, but then this is very inconvenient with many parameters
Upvotes: 1
Views: 357
Reputation: 22507
A failable init is the answer, but you need to declare <T>
, and you need to call the main init
-
class A { // or class A<T>
var count = 0
init() {
}
internal convenience init?<T>(array pArray: [T]) { // <T> not needed if declared at Class level
guard !pArray.isEmpty else {
// it is not correct to init without at least one value
return nil
}
// init with non-empty array
self.init()
self.count = pArray.count
}
}
let n:[String] = ["a"]
if let a = A(array: n) {
print("\(a.count)")
} else {
print("nil")
}
Upvotes: 2
Reputation: 27345
Perhaps you can use fail-able initialiser that will return nil
if array is empty:
class Type<T> {
init?(array pArray: [T]) {
guard !pArray.isEmpty else {
return nil
}
// ...
}
init(value pValue: T) {
// ...
}
}
Upvotes: 1