Reputation: 4521
I have the following structure in my iOS application:
struct MyStruct<T> {
var property1: T
var property2: T
init(property1: T, property2: T) {
self.property1 = property1
self.property2 = property2
}
init(allPropertiesWith value: T) {
self.property1 = value
self.property2 = value
}
}
I also have 2 classes that don't have a common ancestor:
class A { }
class B { }
In my application I have instances of MyStruct<A>
, MyStruct<B>
, MyStruct<A?>
, MyStruct<B?>
and I use them in these functions:
func f1(myStrurct: MyStruct<A?>) { }
func f2(myStrurct: MyStruct<A>) { }
func g2() {
f1(myStrurct: MyStruct<A?>(property2: A()))
}
/* I also have the same functions for MyStruct<B> and MyStruct<B?> */
I cannot modify f1
, f2
and g2
. That's why I created 2 extensions to make initialisation of MyStruct<T>
easier:
extension MyStruct where T == A? {
init(property1: T) {
self.property1 = property1
self.property2 = nil
}
init(property2: T) {
self.property1 = nil
self.property2 = property2
}
}
extension MyStruct where T == B? {
init(property1: T) {
self.property1 = property1
self.property2 = nil
}
init(property2: T) {
self.property1 = nil
self.property2 = property2
}
}
As you can see these extensions are almost the same. Is it possible to refactor it with only 1 extension?
Upvotes: 0
Views: 531
Reputation: 4521
In the answer provided by Rakesha Shastri I found out that I can use protocol
to refactor my code. However to be able to use this solution I need to rewrite other parts of my application. I tried to add the solution by Rakesha Shastri to my application and compile it with Swift 3, Swift 4 or Swift 4.2 (all Swift versions available in Xcode 10.0), but every time I received a compiler error. It means that currently there are no ways how to solve the problem that I described in this question.
Upvotes: 1
Reputation: 11242
You can make both A
and B
(or whichever class needs it) conform to a dummy protocol and check that for T
.
protocol MyStructProtocol {
}
class A: MyStructProtocol { }
class B: MyStructProtocol { }
extension MyStruct where T == MyStructProtocol? {
init(property1: T) {
self.property1 = property1
self.property2 = nil
}
init(property2: T) {
self.property1 = nil
self.property2 = property2
}
}
Upvotes: 1
Reputation: 781
You don't have to extend anything to create such an easier constructor. Check out the modified version of your struct definition below:
struct MyStruct<T> {
var property1: T?
var property2: T?
init(property1: T? = nil, property2: T? = nil) {
if T.self == String.self {
self.property1 = property1
self.property2 = nil
}
else if T.self == Int.self {
self.property1 = nil
self.property2 = property2
}
}
init(allPropertiesWith value: T) {
self.property1 = value
self.property2 = value
}
}
Then you can use initialize them as you wish with following lines.
MyStruct<String>(property2: "sadsad")
MyStruct<Int>(property1: 23)
Upvotes: 0