Swift 泛型:需要类型的加法和乘法能力 [英] Swift generics: requiring addition and multiplication abilities of a type

查看:24
本文介绍了Swift 泛型:需要类型的加法和乘法能力的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试 Swift 书中的一些示例,即他们拥有的引入下标选项的矩阵示例.这是我的代码:

I'm trying out some examples from the Swift book, namely the matrix example they have which introduces subscript options. This is the code I have:

struct Matrix<T> {
    let rows: Int, columns: Int
    var grid: T[]

    var description: String {
        return "\(grid)"
    }

    init(rows: Int, columns: Int, initialValue: T) {
        self.rows = rows
        self.columns = columns
        grid = Array(count: rows * columns, repeatedValue: initialValue)
    }

    func indexIsValidForRow(row: Int, column: Int) -> Bool {
        return row >= 0 && row < rows && column >= 0 && column < columns
    }

    subscript(row: Int, column: Int) -> T {
        get {
            assert(indexIsValidForRow(row, column: column), "Index out of range")
            return grid[(row * columns) + column]
        }
        set {
            assert(indexIsValidForRow(row, column: column), "Index out of range")
            grid[(row * columns) + column] = newValue
        }
    }
}

这主要是从书中复制的.主要区别在于此处的这一行:

This is mostly copied from the book. A major difference is in this line here:

struct Matrix<T>

据我所知,这告诉编译器我的 Matrix 类可以保存 T 类型的值,由使用此类的代码指定.现在,我想确保可以比较类型 T,所以我可以这样写:

As far as I can tell, this says to the compiler that my Matrix class can hold values of type T, specified by the code using this class. Now, I'd like to make sure that the type T can be compared, so I can write this:

struct Matrix<T: Equatable>

如果我想比较 2 个矩阵,这可能会很有用,这意味着比较它们的值.我还想提供对两个矩阵求和的能力,所以我还应该在这一行中添加一个协议,要求可以添加矩阵用户给出的类型T":

This might be useful in case I want to compare 2 matrices, which would mean comparing their values. I also want to provide the ability to sum two matrices, so I should also add to this line a protocol requiring that the type 'T' given by the user of the matrix can be added:

struct Matrix<T: Equatable, "Summable">

同样,我还想说:

struct Matrix<T: Equatable, "Summable", "Multipliable">

问题 1: 我可以使用什么协议名称?我怎样才能做到这一点?

Question 1: What protocol name can I use? How can I achieve this?

在相关说明中,要使用+"运算符添加加法能力,我应该声明一个这样的函数(这也适用于乘法):

On a related note, to add addition abilities using the '+' operator, I should declare a function like this (this applies also to multiplication):

@infix func + (m1: Matrix<T>, m2: Matrix<T>) -> Matrix<T> {
    // perform addition here and return a new matrix
    return result
}

但是,Xcode 不接受此代码.更具体地说,这个 ) ->矩阵 T{ 产生错误:Use of undeclared type 'T'.我所说的 <T> 的意思是结果将是一个矩阵,该矩阵具有两个输入矩阵的相同类型,但我可能完全弄乱了语法.

However, this code is not accepted by Xcode. More specifically, this ) -> Matrix<T> { produces the error: Use of undeclared type 'T'. What I mean by that <T> is that the result will be a matrix that has the same type of the two input matrices, but I'm probably messing the syntax completely.

问题 2:如何为相加结果提供类型信息?

Question 2: How can I provide type information to the result of the addition?

推荐答案

这是你的第二个问题(但你真的应该问两个单独的问题):

Here's for your second question (but you really should ask two separate questions):

@infix func + <T> (m1: Matrix<T>, m2: Matrix<T>) -> Matrix<T> { ... }

对于你的第一个问题:在解决它之前,这里是为类型参数定义多个约束的语法:

For your first question: before solving it, here's the syntax to define multiple constraints for type parameter:

struct Matrix<T where T: Equatable, T: Summable, T: Multipliable> {...}

或者,正如 GoZoner 在评论中所写:

or, as GoZoner writes in the comments:

struct Matrix<T: protocol<Equatable, Summable, Multipliable>> {...}

但我们不需要它.首先,定义一个新协议并列出您需要的操作.你甚至可以让它扩展 Equatable:

But we're not going to need it. First, define a new protocol and list the operations that you need. You can even make it extend Equatable:

protocol SummableMultipliable: Equatable {
    func +(lhs: Self, rhs: Self) -> Self
    func *(lhs: Self, rhs: Self) -> Self
}

然后,为您想要符合的类型提供扩展.在这里,对于 IntDouble,扩展甚至是空的,因为所需操作的实现是内置的:

Then, provide extensions for the types that you want to conform. Here, for Int and Double, the extensions are even empty, as the implementation of the needed ops is built-in:

extension Int: SummableMultipliable {}
extension Double: SummableMultipliable {}

然后,在类型参数上声明类型约束:

Then, declare your type constraint on the type parameter:

struct Matrix<T: SummableMultipliable> { ... }

最后,你可以写这样的东西:

Finally, you can write stuff like this:

let intMat = Matrix<Int>(rows: 3, columns: 3, initialValue: 0)
let doubleMat = Matrix<Double>(rows: 3, columns: 3, initialValue: 0)
let i: Int = intMat[0,0]
let d: Double = doubleMat[0,0]

您需要做的最后一件事是在操作符的定义中插入类型约束:

The last thing you'll need is to insert the type constraint in the definition of your operator:

@infix func + <T: SummableMultipliable> (m1: Matrix<T>, m2: Matrix<T>) -> Matrix<T> { ... }

这篇关于Swift 泛型:需要类型的加法和乘法能力的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆