2015-04-29 54 views
0

我对使用泛型类型T的类可能是IntDouble的内部数组有问题。函数average应计算数组中所有IntDouble值的平均值。具有泛型类型的算术运算符(+, - ,/,*)的使用

class MathStatistics<T: Comparable> { 
    var numbers = [T]() 

    func average() -> Double? { 
     if numbers.count == 0 { 
      return nil 
     } 

     var sum:T 

     for value in numbers { 
      sum = sum + value 
     } 

     return (sum/numbers.count) 
    } 
} 

Xcode的报告一致的错误下面几行:

sum = sum + value 二元运算符 '+' 不能申请两个T operants

return (sum/numbers.count) 找不到一个重载 '/' 是接受提供的参数

+0

你为什么要使用可比性?为什么不把整数转换为双精度? –

+0

这应该回答你的问题的一个主要部分:[什么协议应该采用的泛型函数采取任何数字类型作为参数在Swift?](http://stackoverflow.com/questions/25575513/what -protocol-应待采用逐a型换一个泛型函数到取任何-NUM)。如果您希望所有可能的类型都可以转换为Double,则必须扩展协议。 –

+0

'Comparable'我需要其他功能,为了简化示例,我在此排除了这些功能。 – Morpheus78

回答

3

为此,您需要创建一个新的,让Swift知道的任何实例3210可能会对它进行数值运算,例如:

protocol NumericType: Equatable, Comparable { 
    func +(lhs: Self, rhs: Self) -> Self 
    func -(lhs: Self, rhs: Self) -> Self 
    func *(lhs: Self, rhs: Self) -> Self 
    func /(lhs: Self, rhs: Self) -> Self 
    func %(lhs: Self, rhs: Self) -> Self 
    init(_ v: Int) 
} 

extension Double : NumericType {} 
extension Int  : NumericType {} 

来源:What protocol should be adopted by a Type for a generic function to take any number type as an argument in Swift?

现在,当你定义MathStatistics类:

class MathStatistics<T: NumericType> { 
    var numbers = [T]() 

    func average() -> T? { 
     if numbers.count == 0 { 
      return nil 
     } 

     let sum = numbers.reduce(T(0)) { $0 + $1 } 
     return sum/T(numbers.count) 
    } 
} 

现在你可以使用MathsStatistics像这样:

let stats = MathStatistics<Int>() 
stats.numbers = [1, 3, 5] 
println(stats.average()) // Prints: Optional(3) 
+0

完美,这正是我所期待的! – Morpheus78

+0

太好了,我很高兴能帮到你! – ABakerSmith

2

如果你的意图是co mpute平均在浮点算术 然后则必须定义,其描述 ,其可以被转换为Double所有类型的协议:

protocol DoubleConvertible { 
    var doubleValue : Double { get } 
} 

extension Double : DoubleConvertible { 
    var doubleValue : Double { return self } 
} 

extension Int : DoubleConvertible { 
    var doubleValue : Double { return Double(self) } 
} 

那么你的类将是:

class MathStatistics<T: DoubleConvertible> { 
    var numbers = [T]() 

    func average() -> Double? { 
     if numbers.count == 0 { 
      return nil 
     } 

     var sum = 0.0 
     for value in numbers { 
      sum = sum + value.doubleValue 
     } 
     return (sum/numbers.count.doubleValue) 
    } 
} 

示例:

let stats = MathStatistics<Int>() 
stats.numbers = [3, 5,2] 
println(stats.average()) // Optional(3.33333333333333) 
+0

似乎不适合我。我总是收到'sum = sum + value.doubleValue'行的错误消息'T没有名为doubleValue'的成员。如果我正确地理解了它,那么'T:DoubleConvertible>只是说'T'支持这个协议。我是否必须在'MathStatistics'中实现'var doubleValue ...'? – Morpheus78

+0

@ Morpheus78:奇怪。在发布之前,我已经测试了该代码,并且按预期进行了编译和工作。 –

+0

@ Morpheus78:...您是否添加了Double和Int的扩展方法? –

0

当我想在泛型T上使用两个协议时,似乎SWIFT中存在一个错误。

以下代码完美地工作。

protocol DoubleConvertible { 
    var doubleValue : Double { get } 
} 

protocol NumericType: Equatable, Comparable, DoubleConvertible { 
    func +(lhs: Self, rhs: Self) -> Self 
    func -(lhs: Self, rhs: Self) -> Self 
    func *(lhs: Self, rhs: Self) -> Self 
    func /(lhs: Self, rhs: Self) -> Self 
    func %(lhs: Self, rhs: Self) -> Self 
    init(_ v: Int) 
    init(_ v: Double) 
} 

extension Double : NumericType { 
    var doubleValue : Double { return self } 
} 

extension Int : NumericType { 
    var doubleValue : Double { return Double(self) } 
} 

class MathStatistics<T: NumericType> { 
    var numbers = [T]() 

    func average() -> Double? { 
     if numbers.count == 0 { 
      return nil 
     } 

     let sum = numbers.reduce(T(0)) { $0 + $1 } 
     return sum.doubleValue/numbers.count.doubleValue 
    } 
} 

这个版本产生错误T does not have a member named doubleValue符合return sum.doubleValue/numbers.count.doubleValue

protocol NumericType: Equatable, Comparable { 
    func +(lhs: Self, rhs: Self) -> Self 
    func -(lhs: Self, rhs: Self) -> Self 
    func *(lhs: Self, rhs: Self) -> Self 
    func /(lhs: Self, rhs: Self) -> Self 
    func %(lhs: Self, rhs: Self) -> Self 
    init(_ v: Int) 
    init(_ v: Double) 
} 

protocol DoubleConvertible { 
    var doubleValue : Double { get } 
} 

extension Double : DoubleConvertible { 
    var doubleValue : Double { return self } 
} 

extension Int : DoubleConvertible { 
    var doubleValue : Double { return Double(self) } 
} 

class MathStatistics<T: NumericType, DoubleConvertible > { 
    var numbers = [T]() 

    func average() -> Double? { 
     if numbers.count == 0 { 
      return nil 
     } 

     let sum = numbers.reduce(T(0)) { $0 + $1 } 
     return sum.doubleValue/numbers.count.doubleValue // error T does not have a member named doubleValue 
    } 
} 
+1

尝试用'T:protocol 或'T替换'T:NumericType,DoubleConvertible',其中T:NumericType,T:DoubleConvertible'。 – ABakerSmith