我希望编写的代码允许我像这样在不同类型之间建立绑定(bind):
Map.add(1.0).to(CGPointZero) // (x:1.0, y:1.0)
这是一个人为的例子,但如果它可以工作,可能是一种捕捉关系的好方法。在 C++ 中,这将是直截了当的,您将创建如下内容:
class Binding<typename FromType> {
FromType from;
to<typename ToType>(ToType toType) {
return from + toType
}
}
class Map {
Binding<T> add<T>(t:T) {
return Binding<T>(t:t)
}
}
编译器会判断是否可以添加这些类型。
不过,Swift 是另一种动物,您需要在使用协议(protocol)类型之前捕获这种关系。它可能看起来像这样:
public protocol ScalarArithmetic {
typealias SomeScalarType
func +(lhs: SomeScalarType, rhs: Self) -> Self
}
// Double + CGPoint
public func + (lhs:Double, rhs:CGPoint) -> CGPoint {
return CGPoint(x: rhs.x + CGFloat(lhs), y:rhs.y + CGFloat(lhs))
}
// Float + CGPoint
public func + (lhs:Float, rhs:CGPoint) -> CGPoint {
return CGPoint(x: rhs.x + CGFloat(lhs), y:rhs.y + CGFloat(lhs))
}
class Binding<T> {
var from: T
init(t:T) { self.from = t }
func to<S:ScalarArithmetic where S.SomeScalarType == T>(s:S) -> S {
return self.from + s
}
}
class Map {
class func add<T>(t:T) -> Binding<T> {
return Binding<T>(t:t)
}
}
但问题是如何绑定(bind)类型 - 让我们以 CGPoint 为例,使用多个标量类型,因此上述机制可用于一系列绑定(bind)(如上面的 C++ 示例)。
这行不通,因为编译器不喜欢重复的语句:
extension CGPoint : ScalarArithmetic {
typealias SomeScalarType = Double
}
extension CGPoint : ScalarArithmetic {
typealias SomeScalarType = Float
}
我尝试在它自己的协议(protocol)中捕获标量类型——也许这就是实现它的方式,但它把问题推向了道路:
public protocol SomeScalarType {}
extension Double: SomeScalarType {}
extension Float: SomeScalarType {}
public protocol ScalarArithmetic {
func +(lhs: SomeScalarType, rhs: Self) -> Self
}
// Double + CGPoint
public func + (lhs:Double, rhs:CGPoint) -> CGPoint {
return CGPoint(x: rhs.x + CGFloat(lhs), y:rhs.y + CGFloat(lhs))
}
// Float + CGPoint
public func + (lhs:Float, rhs:CGPoint) -> CGPoint {
return CGPoint(x: rhs.x + CGFloat(lhs), y:rhs.y + CGFloat(lhs))
}
extension CGPoint: ScalarArithmetic {} // does not conform to ScalarArithmetic
// since it is not implemented in terms of the ScalarArithmetic protocol,
// despite having the necessary operators.
所以为了让自己接受我自己的答案,是否留下唯一的选择,使 ScalarType “足够可转换”,它可以转换为所需的原始类型:
public func + (lhs:SomeScalarType, rhs:SomeScalarType) -> CGPoint {
return CGPoint(x: rhs.x + CGFloat(lhs), y:rhs.y + CGFloat(lhs))
}
我该怎么做,和/或有更好的解决方案吗?
提前致谢。
最佳答案
Swift 有意不为你强制转换类型。这是一种语言选择,绕过它会很困难。您不能 + 任意数字类型。您的 C++ 示例之所以有效,是因为可以添加任意数量的东西,而在 Swift 中则不能。
IMO,对于您要执行的操作,正确答案是:
public func + (lhs:Double, rhs:CGPoint) -> CGPoint {
return CGPoint(x: rhs.x + CGFloat(lhs), y:rhs.y + CGFloat(lhs))
}
句号。但是附加到 + 是一件很糟糕的事情。您不能有意义地 + 标量和矢量。这种事情最好定义为:
public func + (lhs:CGPoint, rhs:CGPoint) -> CGPoint {
return CGPoint(x: rhs.x + lhs.x, y:rhs.y + lhs.y)
}
然后制作你想要添加的 CGPoint(即使你必须创建一个 Diagonal(1) 函数来提供帮助。我知道这是一个人为的例子,但我希望对于整个问题也是如此。使类型自动强制转换应该非常小心。创建一个 init 几乎总是更好,它可以让你明确地将一个转换为另一个。然后运营商是有道理的。
这就是 Swift 允许更强大的类型安全性的全部优势。例如,我有一些这样的代码:
// Frequency and Time are reciprocols
public func *(lhs: SignalTime, rhs: SignalFrequency) -> Double { return lhs.seconds * rhs.hertz }
public func *(lhs: SignalFrequency, rhs: SignalTime) -> Double { return rhs * lhs }
public func /(lhs: Double, rhs: SignalFrequency) -> SignalTime { return SignalTime(seconds: lhs / rhs.hertz) }
public func /(lhs: Double, rhs: SignalTime) -> SignalFrequency { return SignalFrequency(hertz: lhs / rhs.seconds) }
// Frequency can be scaled by a constant
public func *(lhs: SignalFrequency, rhs: Double) -> SignalFrequency { return SignalFrequency(hertz: lhs.hertz * rhs) }
public func *(lhs: Double, rhs: SignalFrequency) -> SignalFrequency { return rhs * lhs }
这一切都非常明确甚至乏味,但它应该如此。有组合这些类型的有用方法,也有组合这些类型的非法方法。 x/y 返回与 y/x 完全不同的类型。这样做在编译阶段发现了几个“哦,我不小心将频率乘以频率”的错误。试图用最少的代码使所有这些“神奇地工作”往往会以允许非法操作的方式过度扩展类型。
我会避免使用 ScalarArithmetic,直到您有一个非常好的且明确的用例。如果你有一个不同的例子,看看会很有趣,但我希望答案是相似的。小心过度强制。
关于ios - Swift:协议(protocol):捕获类型之间的兼容性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25874300/
我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此
在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我正在检查一个Rails项目。在ERubyHTML模板页面上,我看到了这样几行:我不明白为什么不这样写:在这种情况下,||=和ifnil?有什么区别? 最佳答案 在这种特殊情况下没有区别,但可能是出于习惯。每当我看到nil?被使用时,它几乎总是使用不当。在Ruby中,很少有东西在逻辑上是假的,只有文字false和nil是。这意味着像if(!x.nil?)这样的代码几乎总是更好地表示为if(x)除非期望x可能是文字false。我会将其切换为||=false,因为它具有相同的结果,但这在很大程度上取决于偏好。唯一的缺点是赋值会在每次运行
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总
我正在尝试使用ruby编写一个双线程客户端,一个线程从套接字读取数据并将其打印出来,另一个线程读取本地数据并将其发送到远程服务器。我发现的问题是Ruby似乎无法捕获线程内的错误,这是一个示例:#!/usr/bin/rubyThread.new{loop{$stdout.puts"hi"abc.putsefsleep1}}loop{sleep1}显然,如果我在线程外键入abc.putsef,代码将永远不会运行,因为Ruby将报告“undefinedvariableabc”。但是,如果它在一个线程内,则没有错误报告。我的问题是,如何让Ruby捕获这样的错误?或者至少,报告线程中的错误?
📢博客主页:https://blog.csdn.net/weixin_43197380📢欢迎点赞👍收藏⭐留言📝如有错误敬请指正!📢本文由Loewen丶原创,首发于CSDN,转载注明出处🙉📢现在的付出,都会是一种沉淀,只为让你成为更好的人✨文章预览:一.分辨率(Resolution)1、工业相机的分辨率是如何定义的?2、工业相机的分辨率是如何选择的?二.精度(Accuracy)1、像素精度(PixelAccuracy)2、定位精度和重复定位精度(RepeatPrecision)三.公差(Tolerance)四.课后作业(Post-ClassExercises)视觉行业的初学者,甚至是做了1~2年