0

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?

Roman Podymov
  • 4,168
  • 4
  • 30
  • 57

3 Answers3

1

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
    }
}
Rakesha Shastri
  • 11,053
  • 3
  • 37
  • 50
1

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.

Roman Podymov
  • 4,168
  • 4
  • 30
  • 57
0

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)
Yusuf Kamil AK
  • 771
  • 8
  • 17