我知道我们可以使用 AnyObject
来指定泛型为任何引用类型:
class Foo<T: AnyObject> {
// ...
}
但是有没有一种方法可以指定我们的泛型只应该是值类型,不允许引用类型呢?
我知道我们可以使用 AnyObject
来指定泛型为任何引用类型:
class Foo<T: AnyObject> {
// ...
}
但是有没有一种方法可以指定我们的泛型只应该是值类型,不允许引用类型呢?
// some code for testing
class C { } // just a simple class as an example for a reference type
var c = C()
var d: Double = 0.9 // a value type
扩展
解决方案1protocol ValueType { }
extension Double : ValueType { }
extension Int : ValueType { }
// ... all value types to be added
func printT1 <T: ValueType> (input: T) {
println("\(input) is value")
}
printT1(d) // Does work
//printT1(c) // Does not work
但是正如评论中提到的,它确实可以工作但不可行,因为用户自定义值类型必须实现此协议。
func printT <T: AnyObject> (input: T) {
println("\(input) is reference")
}
func printT <T: Any> (input: T) {
println("\(input) is value")
}
assert
实现的解决方案 3另一个解决方案可以通过 assert
来实现。
func printT <T: Any> (input: T) {
print("\(input) is " + ((T.self is AnyObject) ? "reference" : "value"))
}
where
子句的“解决方案”4我认为这是最好的解决方案。不幸的是,无法
func printT <T: Any where T: ~AnyObject > (input: T) {
println("\(input) is value")
}
或类似的方式。也许在未来的Swift版本中可能会实现。
==
检查“相等性”,而Comparable表示除此之外还有一个严格的顺序 <
。这与值类型和引用类型无关。(例如,NSObject是一种引用类型并符合Equatable协议。) - Martin Rwhere
子句对此起作用,并且我不确定为什么您提到它却没有包含示例。 - nhgrifenum
和struct
不会自动符合它(它们必须被添加... 这几乎意味着我无法将这段代码真正地分发到库中)。此外,没有任何阻止用户创建的类符合该协议并被使用的机制。 - nhgrif===
对于AnyObject
进行了定义,因此可能无法使用它的任何内容都是值类型。确定某个内容是否可以使用===
似乎与确定它是否为AnyObject
相同。我不确定这比我们可以使用AnyObject
来知道它是引用类型更有帮助。 - nhgrif
isUniquelyReferenced()
,以查看是否可以获得对底层目标的运行时断言(我假设的是确保对象不能在背后更改)。我肯定会在 devforums 上提出你的用例(https://devforums.apple.com/community/tools/languages/swift)。这是一个非常有趣的问题。 - Rob Napierclass
和struct
之间所有的相似之处和不同之处。在下方你还会找到“结构体和枚举是值类型(Value Types)”和“类是引用类型(Reference Types)”的部分。 - Slipp D. ThompsonUnsafeMutablePointer
不是一个引用类型 - 它是一个具有内存地址作为其数据的值类型。该内存地址可以以临时方式用作引用,但UnsafeMutablePointer
的实例仍然是一个值类型。最重要的是,这种临时使用不是使用 Swift 的正常“本地”方式 -UnsafeMutablePointer
主要作为桥梁提供,以便能够使用 C API,因此 Swift 必须有对所有 C 指针疯狂行为的支持。 - Slipp D. Thompson