Swift中是否没有默认(T)?
我试图将Swift book中的矩阵示例移植为通用的 以下是我目前得到的信息:Swift中是否没有默认(T)?,swift,generics,Swift,Generics,我试图将Swift book中的矩阵示例移植为通用的 以下是我目前得到的信息: struct Matrix<T> { let rows: Int, columns: Int var grid: T[] init(rows: Int, columns: Int, repeatedValue: T) { self.rows = rows self.columns = columns grid = Array(co
struct Matrix<T> {
let rows: Int, columns: Int
var grid: T[]
init(rows: Int, columns: Int, repeatedValue: T) {
self.rows = rows
self.columns = columns
grid = Array(count: rows * columns, repeatedValue: repeatedValue)
}
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
}
}
}
结构矩阵{
让行:Int,列:Int
变量网格:T[]
init(行:Int,列:Int,repeatedValue:T){
self.rows=行
self.columns=列
网格=数组(计数:行*列,repeatedValue:repeatedValue)
}
func indexIsValidForRow(行:Int,列:Int)->Bool{
返回行>=0&&rowrepeatedValue:T
传递给构造函数
在C#中,我只会使用
default(T)
来表示数字,false
表示布尔值,null
表示引用类型。我知道Swift不允许非可选类型使用nil
,但我仍然好奇传递显式参数是否是唯一的方法,或者我是否有一些与default(t)
等价的方法。没有。Swift强制您指定默认值,就像处理变量和字段一样。Swift有默认值概念的唯一情况是可选类型,它是nil
(optional.None
)。不确定的“是”。可以使用协议约束指定泛型类或函数仅与实现默认init函数(无参数)的类型一起工作的要求。这样做的后果很可能是不好的(它不像你想象的那样工作),但它最接近你所要求的,可能比“不”的答案更接近
对我来说,我个人发现这在开发新泛型类的过程中很有帮助,然后最终我消除了约束并解决了剩余的问题。仅要求具有默认值的类型将限制泛型数据类型的用途
public protocol Defaultable
{
init()
}
struct Matrix<Type: Defaultable>
{
let rows: Int
let columns: Int
var grid: [Type]
init(rows: Int, columns: Int)
{
self.rows = rows
self.columns = columns
grid = Array(count: rows * columns, repeatedValue: Type() )
}
}
公共协议默认值
{
init()
}
结构矩阵
{
让行:Int
let列:Int
变量网格:[类型]
init(行:Int,列:Int)
{
self.rows=行
self.columns=列
网格=数组(计数:行*列,repeatedValue:Type())
}
}
有一种方法可以在swift中获得相当于默认值(T)
,但它不是免费的,并且有相关的危险:
public func defaultValue<T>() -> T {
let ptr = UnsafeMutablePointer<T>.alloc(1)
let retval = ptr.memory
ptr.dealloc(1)
return retval;
}
在问题行,Swift认为t
已经初始化,因为Swift的语义是这样说的:不能有未初始化的值类型的变量。除了因为default
破坏了这些语义之外。执行赋值时,Swift向值见证表发出调用,以销毁现有类型。这将包括在字段x
上调用release
的代码,因为Swift语义表示对象的实例永远不会nil
。然后你会遇到运行时崩溃
然而,我有理由从另一种语言与Swift进行互操作,并且我必须传入一个可选类型。不幸的是,由于种种原因(至少我还没有找到一种方法),Swift没有为我提供一种在运行时构造可选项的方法,我也无法轻松地模拟一种方法,因为可选项是根据通用枚举实现的,而枚举使用的是一种缺乏文档的5策略实现来打包枚举的负载
我通过传递一个元组来解决这个问题,我将称之为美杜莎元组,只是为了笑:(value:T,present:Bool)
,它有一个约定,如果present
为true
,那么value
保证有效,否则无效。我现在可以安全地使用它进行互操作:
public func toOptional<T>(optTuple: (value:T, present:Bool)) -> T?
{
if optTuple.present { return optTuple.value }
else { return nil }
}
public func fromOptional<T>(opt: T?) -> (T, Bool)
{
if opt != nil { return (opt!, true) }
else {
return (defaultValue(), false)
}
}
public func to可选(optTuple:(值:T,当前值:Bool))->T?
{
如果optTuple.present{返回optTuple.value}
else{return nil}
}
public func from可选(opt:T?->(T,Bool)
{
如果opt!=nil{return(opt!,true)}
否则{
返回值(defaultValue(),false)
}
}
这样,我的调用代码以元组形式传递,而不是可选的和接收代码,并将其转换为可选的(反之亦然)。我喜欢这种方法。我有一本有
集值的字典。我提供了扩展字典,其中Value:Defaultable{…}
,我可以提供一个实现:subscript(key:key)->Value{…}
——一个非可选的返回类型,它大大简化了使用字典的代码,并为Dictionary
提供了我在本例中实际需要的语义。请注意,由于repeatingValue
不是@autoclosure
,如果Type
是引用类型,则数组将填充相同的对象,而不是初始化为相同值的对象的副本。我认为这可能会有所帮助。
public func toOptional<T>(optTuple: (value:T, present:Bool)) -> T?
{
if optTuple.present { return optTuple.value }
else { return nil }
}
public func fromOptional<T>(opt: T?) -> (T, Bool)
{
if opt != nil { return (opt!, true) }
else {
return (defaultValue(), false)
}
}