代码之家  ›  专栏  ›  技术社区  ›  Roman Podymov

如何为仅对swift 4.1中的可选通用参数可用的通用结构创建扩展?

  •  0
  • Roman Podymov  · 技术社区  · 6 年前

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

    我还有两个没有共同祖先的类:

    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 . 这就是为什么我创建了两个扩展来初始化 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 回复  |  直到 6 年前
        1
  •  1
  •   Rakesha Shastri    6 年前

    两者都可以 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
        }
    }
    
        2
  •  0
  •   Yusuf Kamil AK    6 年前

    您不必扩展任何东西来创建这样简单的构造函数。请查看以下结构定义的修改版本:

    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)
    
        3
  •  0
  •   Roman Podymov    6 年前

    answer 提供的 Rakesha Shastri 我发现我可以用 protocol 重构我的代码。但是要使用这个解决方案,我需要重写应用程序的其他部分。我试图将Rakesha Shastri的解决方案添加到我的应用程序中,并使用Swift 3、Swift 4或Swift 4.2(Xcode 10.0中提供的所有Swift版本)编译它,但每次收到编译器错误时。这意味着目前没有办法解决我在这个问题中描述的问题。