swift – 尝试扩展IntegerType(和FloatingPointType);为什么不能将所有Int类型转换为NSTimeInterval

swift – 尝试扩展IntegerType(和FloatingPointType);为什么不能将所有Int类型转换为NSTimeInterval,第1张

概述(这可能需要一个更好的标题…) 我想在代码中使用一组访问器来快速表达持续时间.例如: 42.seconds3.14.minutes0.5.hours13.days This post说明您不能只使用简单的新协议,扩展,并强制IntegerType和FloatingPointType采用它.所以我想我只是去更冗余的路由并直接扩展IntegerType(然后重复FloatingPointType (这可能需要一个更好的标题…)

我想在代码中使用一组访问器来快速表达持续时间.例如:

42.seconds3.14.minutes0.5.hours13.days

This post说明您不能只使用简单的新协议,扩展,并强制IntegerType和floatingPointType采用它.所以我想我只是去更冗余的路由并直接扩展IntegerType(然后重复floatingPointType的代码).

extension IntegerType {    var seconds:NSTimeInterval {        return NSTimeInterval(self)    }}

生成的错误令人困惑:

Playground execution Failed: /var/folders/2k/6y8rslzn1m95gjpg534j7v8jzr03tz/T/./lldb/9325/playground131.swift:31:10: error: cannot invoke initializer for type 'NSTimeInterval' with an argument List of type '(Self)'                return NSTimeInterval(self)                       ^/var/folders/2k/6y8rslzn1m95gjpg534j7v8jzr03tz/T/./lldb/9325/playground131.swift:31:10: note: overloads for 'NSTimeInterval' exist with these partially matching parameter Lists: (Double),(UInt8),(Int8),(UInt16),(Int16),(UInt32),(Int32),(UInt64),(Int64),(UInt),(Int),(float),(float80),(String),(CGfloat),(NSNumber)                return NSTimeInterval(self)

让我感到困惑的是,它似乎说我不能用(Self)做一个NSTimeInterval()初始化器,但是Self表示的所有内容都列在下一行,它显示了NSTimeInterval的所有可能的初始化器.我在这里错过了什么?

旁白:如果有一个关于Swift类型系统的精心编写的教程并做这些事情,我会很高兴. Apple的稀疏Swift文档中没有很好地介绍中间/高级内容

更新/澄清:

我想要的是能够评估上述任何表达式:

42.seconds   --> 423.14.minutes --> 188.40.5.hours    --> 180013.days      --> 1123200

此外,我希望这些的返回类型是NSTimeInterval(Double的类型别名),这样:

42.seconds is NSTimeInterval   --> true3.14.minutes is NSTimeInterval --> true0.5.hours is NSTimeInterval    --> true13.days is NSTimeInterval      --> true

我知道我可以通过简单地扩展Double和Int来实现这一点:

extension Int {    var seconds:NSTimeInterval {        return NSTimeInterval(self)    }    var minutes:NSTimeInterval {        return NSTimeInterval(self * 60)    }    var hours:NSTimeInterval {        return NSTimeInterval(self * 3600)    }    var days:NSTimeInterval {        return NSTimeInterval(self * 3600 * 24)    }}extension Double {    var seconds:NSTimeInterval {        return NSTimeInterval(self)    }    var minutes:NSTimeInterval {        return NSTimeInterval(self * 60)    }    var hours:NSTimeInterval {        return NSTimeInterval(self * 3600)    }    var days:NSTimeInterval {        return NSTimeInterval(self * 3600 * 24)    }}

但是我也希望以下表达式起作用:

let foo:Uint = 4242foo.minutes                   --> 254520foo.minutes is NSTimeInterval --> true

这不会起作用,因为我只扩展了Int,而不是UInt.我可以冗余地扩展Uint,然后是UInt16,然后是Int16等….

我想将Int扩展扩展为IntegerType,如原始列表中所示,这样我就可以获得所有整数类型的转换.然后对floatingPointType执行相同 *** 作,而不是专门为Double.但是,这会产生原始错误.我想知道为什么我不能像通常所示那样扩展IntegerType.除了列表中显示的那些之外是否还有其他IntegerType采用者,这使得NSTimeInterval()初始化程序无法解析?

解决方法

I Could redundantly extend Uint,and then UInt16,and then Int16,etc….

正确.这就是今天在Swift中的表现.您不能声明协议符合扩展中的其他协议. (“为什么?”“因为编译器不允许它.”)

但这并不意味着你必须重写所有的实现.您目前必须实施三次(如果您想要float80,则需要四次,但这在这里似乎没有用).首先,您声明您的协议.

import Foundation// Declare the protocolprotocol TimeIntervalConvertible {    func toTimeInterval() -> NSTimeInterval}// Add all the helpers you wantedextension TimeIntervalConvertible {    var seconds:NSTimeInterval {        return NSTimeInterval(self.toTimeInterval())    }    var minutes:NSTimeInterval {        return NSTimeInterval(self.toTimeInterval() * 60)    }    var hours:NSTimeInterval {        return NSTimeInterval(self.toTimeInterval() * 3600)    }    var days:NSTimeInterval {        return NSTimeInterval(self.toTimeInterval() * 3600 * 24)    }}// ProvIDe the implementations. floatingPointType doesn't have an equivalent to// toIntMax(). There's no todouble() or tofloatMax(). Converting a float to// a Double injects data noise in a way that converting Int8 to IntMax does not.extension Double {    func toTimeInterval() -> NSTimeInterval { return NSTimeInterval(self) }}extension float {    func toTimeInterval() -> NSTimeInterval { return NSTimeInterval(self) }}extension IntegerType {    func toTimeInterval() -> NSTimeInterval { return NSTimeInterval(self.toIntMax()) }}// And then we tell it that all the int types can get his implementationextension Int: TimeIntervalConvertible {}extension Int8: TimeIntervalConvertible {}extension Int16: TimeIntervalConvertible {}extension Int32: TimeIntervalConvertible {}extension Int64: TimeIntervalConvertible {}extension UInt: TimeIntervalConvertible {}extension UInt8: TimeIntervalConvertible {}extension UInt16: TimeIntervalConvertible {}extension UInt32: TimeIntervalConvertible {}extension UInt64: TimeIntervalConvertible {}

这就是当前在Swift中完成数字类型的方式.通过stdlib查看.你会看到很多东西:

extension Double {    public init(_ v: UInt8)    public init(_ v: Int8)    public init(_ v: UInt16)    public init(_ v: Int16)    public init(_ v: UInt32)    public init(_ v: Int32)    public init(_ v: UInt64)    public init(_ v: Int64)    public init(_ v: UInt)    public init(_ v: Int)}

在某些情况下讨论“类似数字的东西”会不会很好?当然.你今天不能在斯威夫特.

“为什么?”

因为编译器没有实现它.有一天它可能会.在此之前,为您想要的每种类型创建扩展.一年前,这将采取更多的代码.

请注意,虽然其中一些是“Swift还没有这个功能”,但有些也是故意的. Swift故意要求在数字类型之间进行显式转换.数字类型之间的转换通常会导致信息丢失或注入噪音,并且历史上一直是棘手的错误来源.每次转换数字时都应该考虑这个问题.例如,从Int64到Int8或从UInt8到Int8的明显情况可能会丢失信息.但是从Int64到Double也会丢失信息.并非所有64位整数都可以表示为Double.这是一个微妙的事实,在处理非常大的数字时会经常烧伤人,Swift会鼓励你处理它.即使将float转换为Double也会将噪声注入数据中.表示为float的1/10是与表示为Double的1/10不同的值.当你将float转换为Double时,你的意思是扩展重复数字吗?根据您选择的内容,您将引入不同类型的错误,因此您需要选择.

另请注意,您的.days可能会引入细微的错误,具体取决于确切的问题域.一天不总是24小时.根据DST的变化,它可以是23小时或25小时.有时这很重要.有时却没有.但是,对于将“天”视为特定秒数而非常谨慎是一个理由.通常,如果你想在几天内工作,你应该使用NSDate,而不是NSTimeInterval.我对那个特别的人非常怀疑.

顺便说一下,您可能对my old implementation of this idea感兴趣.而不是使用语法:

1.seconds

我用了语法:

1 * Second

然后重载乘法返回结构而不是Double.以这种方式返回结构可以提供更好的类型安全性.例如,我可以输入“time * frequency == cycles”和“cycles / time == frequency”,这是Double无法做到的.不幸的是,NSTimeInterval不是一个单独的类型;它只是Double的另一个名字.因此,您在NSTimeInterval上放置的任何方法都应用于每个Double(有时候很奇怪).

就个人而言,我可能会这样解决整个问题:

let Second: NSTimeInterval = 1let Seconds = Secondlet Minute = 60 * Secondslet Minutes = Minutelet Hour = 60 * Minuteslet Hours = Hourlet x = 100*Seconds

您甚至不需要重载运算符.它已经为你完成了.

总结

以上是内存溢出为你收集整理的swift – 尝试扩展IntegerType(和FloatingPointType);为什么不能将所有Int类型转换为NSTimeInterval全部内容,希望文章能够帮你解决swift – 尝试扩展IntegerType(和FloatingPointType);为什么不能将所有Int类型转换为NSTimeInterval所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1005141.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存