Swift 泛型 *= 操作错误
Swift generics *= operator error
我有以下简单的结构类型。
import Foundation
import SceneKit
protocol Named {
class var name: String { get }
}
extension Float: Named {
static var name: String { return "Float" }
}
struct Vector3<T: protocol<Named, FloatingPointType>>: Printable { // This protocol solves the generics issue
// Properties
var x, y, z: T
var description: String {
return "Vector3<\(T.name)>(\(x), \(y), \(z))"
}
// Methods - mutating
mutating func factored(factor: T) {
x *= factor
}
}
我希望能够将创建结构时使用的相同类型作为 factored
的参数。但这会导致 Cannot invoke *= with an argument list of type (T, T)
.
我是否需要实现 *=
运算符以及我最终需要的任何其他运算符?我该怎么做?
编辑
在@matt 提出建议将 Vector3 声明为遵守 FloatingPointType
协议后,问题就解决了。虽然现在我在 factored
方法中得到一个 T is not identical to UInt8
。
这不会编译,因为不能保证您的 T 类型可以相乘,甚至可以分配。您必须 implement/override 命名类型的 = 和 * 运算符才能使其工作。不过,我不确定协议是否甚至可以要求执行运算符。
更新答案
根据@matt 的建议,在这里组合协议可能最有意义:
protocol NamedAndMultipliable {
class var name: String { get }
func *=(inout lhs: Self, rhs: Self)
}
func *=(inout lhs: Int, rhs: Int) {
lhs = lhs * rhs
}
extension Int : NamedAndMultipliable {
static var name: String { return "Int" }
}
extension Double : NamedAndMultipliable {
static var name: String { return "Double" }
}
extension Float : NamedAndMultipliable {
static var name: String { return "Float" }
}
struct Vector3<T: NamedAndMultipliable>: Printable {
// Properties
var x, y, z: T
var description: String {
return "Vector3<\(T.name)>(\(x), \(y), \(z))"
}
// Methods - mutating
mutating func factored(factor: T) {
x *= factor
}
}
原答案
通过执行以下操作,我得到了我认为您想要的结果:
protocol Named {
class var name: String { get }
}
protocol Multipliable {
func *(lhs: Self, rhs: Self) -> Self
}
extension Int : Multipliable {}
extension Double : Multipliable {}
extension Float : Multipliable {}
extension Int : Named {
static var name: String { return "Int" }
}
extension Double : Named {
static var name: String { return "Double" }
}
extension Float : Named {
static var name: String { return "Float" }
}
struct Vector3<T: protocol<Named, Multipliable>>: Printable {
// Properties
var x, y, z: T
var description: String {
return "Vector3<\(T.name)>(\(x), \(y), \(z))"
}
// Methods - mutating
mutating func factored(factor: T) {
x = x * factor
}
}
如果您更喜欢使用 *=
运算符,可以这样做,但如果您也想支持 Int
,则需要为其添加一个函数。
protocol MultipliableIntoSelf {
func *=(inout lhs: Self, rhs: Self)
}
func *=(inout lhs: Int, rhs: Int) {
lhs = lhs * rhs
}
extension Int : MultipliableIntoSelf {}
extension Double : MultipliableIntoSelf {}
extension Float : MultipliableIntoSelf {}
protocol Named {
class var name: String { get }
}
extension Int : Named {
static var name: String { return "Int" }
}
extension Double : Named {
static var name: String { return "Double" }
}
extension Float : Named {
static var name: String { return "Float" }
}
struct Vector3<T: protocol<Named, MultipliableIntoSelf>>: Printable {
// Properties
var x, y, z: T
var description: String {
return "Vector3<\(T.name)>(\(x), \(y), \(z))"
}
// Methods - mutating
mutating func factored(factor: T) {
x *= factor
}
}
我有以下简单的结构类型。
import Foundation
import SceneKit
protocol Named {
class var name: String { get }
}
extension Float: Named {
static var name: String { return "Float" }
}
struct Vector3<T: protocol<Named, FloatingPointType>>: Printable { // This protocol solves the generics issue
// Properties
var x, y, z: T
var description: String {
return "Vector3<\(T.name)>(\(x), \(y), \(z))"
}
// Methods - mutating
mutating func factored(factor: T) {
x *= factor
}
}
我希望能够将创建结构时使用的相同类型作为 factored
的参数。但这会导致 Cannot invoke *= with an argument list of type (T, T)
.
我是否需要实现 *=
运算符以及我最终需要的任何其他运算符?我该怎么做?
编辑
在@matt 提出建议将 Vector3 声明为遵守 FloatingPointType
协议后,问题就解决了。虽然现在我在 factored
方法中得到一个 T is not identical to UInt8
。
这不会编译,因为不能保证您的 T 类型可以相乘,甚至可以分配。您必须 implement/override 命名类型的 = 和 * 运算符才能使其工作。不过,我不确定协议是否甚至可以要求执行运算符。
更新答案
根据@matt 的建议,在这里组合协议可能最有意义:
protocol NamedAndMultipliable {
class var name: String { get }
func *=(inout lhs: Self, rhs: Self)
}
func *=(inout lhs: Int, rhs: Int) {
lhs = lhs * rhs
}
extension Int : NamedAndMultipliable {
static var name: String { return "Int" }
}
extension Double : NamedAndMultipliable {
static var name: String { return "Double" }
}
extension Float : NamedAndMultipliable {
static var name: String { return "Float" }
}
struct Vector3<T: NamedAndMultipliable>: Printable {
// Properties
var x, y, z: T
var description: String {
return "Vector3<\(T.name)>(\(x), \(y), \(z))"
}
// Methods - mutating
mutating func factored(factor: T) {
x *= factor
}
}
原答案
通过执行以下操作,我得到了我认为您想要的结果:
protocol Named {
class var name: String { get }
}
protocol Multipliable {
func *(lhs: Self, rhs: Self) -> Self
}
extension Int : Multipliable {}
extension Double : Multipliable {}
extension Float : Multipliable {}
extension Int : Named {
static var name: String { return "Int" }
}
extension Double : Named {
static var name: String { return "Double" }
}
extension Float : Named {
static var name: String { return "Float" }
}
struct Vector3<T: protocol<Named, Multipliable>>: Printable {
// Properties
var x, y, z: T
var description: String {
return "Vector3<\(T.name)>(\(x), \(y), \(z))"
}
// Methods - mutating
mutating func factored(factor: T) {
x = x * factor
}
}
如果您更喜欢使用 *=
运算符,可以这样做,但如果您也想支持 Int
,则需要为其添加一个函数。
protocol MultipliableIntoSelf {
func *=(inout lhs: Self, rhs: Self)
}
func *=(inout lhs: Int, rhs: Int) {
lhs = lhs * rhs
}
extension Int : MultipliableIntoSelf {}
extension Double : MultipliableIntoSelf {}
extension Float : MultipliableIntoSelf {}
protocol Named {
class var name: String { get }
}
extension Int : Named {
static var name: String { return "Int" }
}
extension Double : Named {
static var name: String { return "Double" }
}
extension Float : Named {
static var name: String { return "Float" }
}
struct Vector3<T: protocol<Named, MultipliableIntoSelf>>: Printable {
// Properties
var x, y, z: T
var description: String {
return "Vector3<\(T.name)>(\(x), \(y), \(z))"
}
// Methods - mutating
mutating func factored(factor: T) {
x *= factor
}
}