Как создать расширение для общей структуры, которая будет доступна только для необязательных общих параметров в Swift 4.1? - PullRequest
0 голосов
/ 11 сентября 2018

В моем приложении iOS есть следующая структура:

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
    }
}

У меня также есть 2 класса, у которых нет общего предка:

class A { }
class B { }

В моем приложении естьэкземпляры MyStruct<A>, MyStruct<B>, MyStruct<A?>, MyStruct<B?>, и я использую их в следующих функциях:

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?> */

Я не могу изменить f1, f2 и g2.Вот почему я создал 2 расширения, чтобы упростить инициализацию MyStruct<T>:

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
    }
}

Как видите, эти расширения почти одинаковы.Возможно ли его рефакторинг только с одним расширением?

Ответы [ 3 ]

0 голосов
/ 11 сентября 2018

Вам не нужно ничего расширять, чтобы создать такой простой конструктор. Проверьте измененную версию вашего определения структуры ниже:

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
    }
}

Затем вы можете использовать их инициализацию по своему усмотрению со следующими строками.

MyStruct<String>(property2: "sadsad")
MyStruct<Int>(property1: 23)
0 голосов
/ 18 сентября 2018

В ответе , предоставленном Ракеша Шастри Я обнаружил, что могу использовать protocol для рефакторинга своего кода. Однако, чтобы иметь возможность использовать это решение, мне нужно переписать другие части моего приложения. Я попытался добавить решение Rakesha Shastri в свое приложение и скомпилировать его с помощью Swift 3, Swift 4 или Swift 4.2 (все версии Swift, доступные в Xcode 10.0), но каждый раз получал ошибку компилятора. Это означает, что в настоящее время нет способов решить проблему, описанную в этом вопросе.

0 голосов
/ 11 сентября 2018

Вы можете сделать так, чтобы A и B (или в зависимости от того, что нужно классу) соответствовали фиктивному протоколу и проверили это для 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
    }
}
...