2016-11-19 35 views
0

我试图依赖注入一个泛型结构到一个类,但我不想重新指定泛型的占位符类型班级也是如此。这会失控,因为任何使用这个类的类都必须执行相同的操作。依赖注入一个通用结构,而不必重新指定占位符类型或约束

举例来说,这个工程:

struct SomeStruct<T : CustomStringConvertible> { 
    let data: T 
} 

class SomeClass { 
    let someStruct = SomeStruct(data: 1) 
} 

但是,如果我想依赖注入其structclass,我得到一个错误:

struct SomeStruct<T : CustomStringConvertible> { 
    let data: T 
} 

class SomeClass { 
    let someStruct: SomeStruct 
    //   ^
    // Reference to generic type 'SomeStruct' requires arguments in <...> 

    init(someStruct: SomeStruct) { 
    //    ^
    // Reference to generic type 'SomeStruct' requires arguments in <...> 
     self.someStruct = someStruct 
    } 
} 

于是我必须指定占位符类型和类型约束再次在class

struct SomeStruct<T : CustomStringConvertible> { 
    let data: T 
} 

class SomeClass<T : CustomStringConvertible> { 
    let someStruct: SomeStruct<T> 

    init(someStruct: SomeStruct<T>) { 
     self.someStruct = someStruct 
    } 
} 

是否有某种方法来解决需要重新指定类中的占位符类型和约束?为什么班级不知道SomeStructdata: CustomStringConvertible

回答

1

不,这是不可能的。你试图描述一个概念,将允许指定一个具体的(class)类型:

class SomeClass { ... } 

但使用非具体类型为成员

class SomeClass { 
    let someStruct: SomeStruct // <-- non-specified generic type, what placeholder should we use? 
} 

对于任何具体类型,其成员还必须具体

// OK 
class SomeClass { 
    let someStruct: SomeStruct<Int> 
} 

,而你可以让通用的成员,如果他们的类型是依赖于所属类型的通用typeholder(SomeClass)本身

// OK (assuming there is no type constraint on the 
//  generic placeholder in the definition of SomeStruct) 
class SomeClass<T> { 
    let someStruct: SomeStruct<T> 
} 

最后,关于“重复”类型的约束:如果由于某种特定类型的通用占位符,说SomeStruct<T>在你的问题,是在某种类型的约束的话,自然(静态类型)的任何typeholder“传播“为泛型SomeStruct的用法中的泛型类型说明符必须确保符合与应用于SomeStruct中泛型占位符相同的约束。因此,您无法避免在SomeStruct被用作通用绑定成员的通用类SomeClass<T: ...>中指定相同的类型约束。

struct SomeStruct<T : CustomStringConvertible> { 
    let data: T 
} 

class SomeClass<T> { 
    let someStruct: SomeStruct<T> 
          /*^this placeholder is not guaranteed to fulfil 
           the type constraints which are applied to the 
           generic typeholder of SomeStruct, hence the 
           illegality */ 
} 
+0

是的,但为什么'SomeClass'必须是通用的?不能只是简单的*拥有*一个通用属性,而不是通用本身?我看不出有什么危险。'SomeClass'不需要更多地了解'data',除了'SomeStruct'说的东西总是这样,'data'将总是'CustomStringConvertible'。在我的例子中,我不关心'SomeClass'甚至在这种用法中知道'data'是'Int'。 – solidcell

+0

@solidcell否,与我的回答顶部相同的论点适用:如果'SomeClass'不是通用的,那么它是一个具体类型,然后它的所有成员必须是具体类型。如果你开始使用泛型,这是一个适用的规则,从Swift的核心概念之一传播出来:强大的输入系统。 – dfri

0

CustomStringConvertible不是具体类型。编译器无法推断出基本类型(符合CustomStringConvertible)的真实含义。

对于这个特定的情况下,如果从someStructSomeClass唯一需要的能力是访问dataString,那么你应该简单地转换您的注入类型(如someStruct)成字符串第一的能力。

+0

不,在我的实际使用案例中,结构中需要更多。这只是一个简化的例子来突出这个问题。 – solidcell