可以使用条件来确定泛型的类型吗?

2024-01-02

在讨论这个问题之前,我将首先解释我想要做什么以及我是如何陷入困境的。


作为我自己的学习练习,我解决了一些已经在 Objective-C 中解决的问题,看看如何使用 Swift 以不同的方式解决它们。我遇到的具体情况是一个小片段,它捕获更改之前和之后的值,并在两者之间进行插值以创建动画的关键帧。

为此我有一个目标Capture包含对象的属性、关键路径和两个id之前和之后的值的属性。后来,当对捕获的值进行插值时,我确保可以通过将每个值包装在一个Value使用类簇根据其包装的值的类型返回适当的类的类,或者nil对于不支持的类型。

这是可行的,我也可以按照相同的模式使其在 Swift 中工作,但感觉不像 Swift。


什么有效

我没有将捕获的值包装为启用插值的方式,而是创建了一个Mixable当类型支持必要的基本算术时,类型可以遵循的协议并使用协议扩展:

protocol SimpleArithmeticType {
    func +(lhs: Self, right: Self) -> Self
    func *(lhs: Self, amount: Double) -> Self
}

protocol Mixable {
    func mix(with other: Self, by amount: Double) -> Self
}

extension Mixable where Self: SimpleArithmeticType {
    func mix(with other: Self, by amount: Double) -> Self {
        return self * (1.0 - amount) + other * amount
    }
}

这部分工作得非常好,并强制执行同质混合(类型只能与其自己的类型混合),而 Objective-C 实现中并未强制执行。

我被困住的地方

下一个逻辑步骤,这就是我陷入困境的地方,似乎是让每个 Capture 实例(现在是一个结构)保存两个相同可混合类型的变量,而不是两个AnyObject。我还将初始化参数从对象和关键路径更改为返回对象的闭包()->T

struct Capture<T: Mixable> {
    typealias Evaluation = () -> T
    let eval: Evaluation

    let before: T
    var after: T {
        return eval()
    }

    init(eval: Evaluation) {
        self.eval = eval
        self.before = eval()
    }
}

当可以推断类型时,这有效,例如:

let captureInt = Capture {
    return 3.0
}
// > Capture<Double>

但不使用键值编码,它返回 AnyObject:\

let captureAnyObject = Capture {
    return myObject.valueForKeyPath("opacity")!
}

错误:无法使用类型为“(() -> _)”的参数列表调用类型“Capture”的初始值设定项

AnyObject不符合Mixable协议,所以我可以理解为什么这不起作用。但我可以检查对象到底是什么类型,并且由于我只涵盖了少数可混合类型,因此我认为我可以涵盖所有情况并返回正确的 Capture 类型。太见了if这甚至可以工作我做了一个更简单的例子

一个更简单的例子

struct Foo<T> {
    let x: T
    init(eval: ()->T) {
        x = eval()
    }
}

当类型推断得到保证时,它会起作用:

let fooInt = Foo {
    return 3
}
// > Foo<Int>
let fooDouble = Foo {
    return 3.0
}
// > Foo<Double>

但当闭包可以返回不同类型时则不然

let condition = true
let foo = Foo {
    if condition {
        return 3
    } else {
        return 3.0
    }
}

错误:无法使用类型为“(() -> _)”的参数列表调用类型“Foo”的初始值设定项

我什至无法自己定义这样的闭包。

let condition = true // as simple as it could be
let evaluation = {
    if condition {
        return 3
    } else {
        return 3.0
    }
}

错误:无法推断当前上下文中的闭包类型

我的问题

这是可以做的事情吗?可以使用条件来确定泛型的类型吗?或者是否有另一种方法来保存相同类型的两个变量,其中类型是根据条件决定的?


Edit

我真正想要的是:

  1. 捕获更改之前和之后的值并保存该对(旧+新)以供以后使用(同类对的异构集合)。
  2. 遍历所有收集的值并删除无法插值的值(除非此步骤可以与收集步骤集成)
  3. 单独插入每个同质对(混合旧+新)。

但在解决这个问题时,这个方向似乎是一个死胡同。我将不得不后退几步并尝试不同的方法(如果我再次陷入困境,可能会问一个不同的问题)。


正如所讨论的Twitter https://twitter.com/davidronnqvist/status/628231101379686400,类型必须在编译时已知。不过,对于问题末尾的简单示例,您可以显式键入

let evaluation: Foo<Double> = { ... }

它会起作用的。

所以在这种情况下Capture and valueForKeyPath:恕我直言,您应该将值转换(安全或强制转换)到Mixable输入您期望的值,它应该可以正常工作。毕竟,我不确定valueForKeyPath:应该根据条件返回不同的类型。

您希望返回两种完全不同类型的确切情况是什么(不能像简单情况那样隐式转换)Int and Double上面)在同一个评估闭包中?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

可以使用条件来确定泛型的类型吗? 的相关文章

  • 使用 UItableviewCell 实现 Google 地图

    我正在尝试在 UItableviewCell 组件内实现谷歌地图 我这样做的方法是在原型单元中定义 GMSMapView 然后使用 dequeueReusableCell 方法配置地图单元 但是 我尝试应用的任何更改都会失败 例如添加标记
  • 在 Swift 中对约束进行动画处理

    我有一个UITextField我想在点击时放大它的宽度 我设置了约束 并确保左侧约束的优先级低于我尝试在右侧设置动画的约束 这是我尝试使用的代码 move the input box UIView animateWithDuration 1
  • Java 泛型:如何为泛型类型指定类类型?

    我有一个 POJO 指定为 MyClass u where U是泛型类型参数 我正在尝试编写一个接受类引用的实用方法Class u
  • Admob 广告无法快速显示

    您好 我正在尝试将 admob 广告添加到已使用 swift 上传到应用商店的应用程序中 我在 admob 中制作了一个应用程序并复制了 appid 和广告 id 并显示了各自的横幅广告和插页式广告 这里的问题是当我写这行时 request
  • .showsPhysics 内存泄漏

    我最近花了 5 个小时尝试调试 Spritekit 应用程序中的内存泄漏 应用程序启动后 我注意到内存使用量略有上升 我花了 5 个小时中的 3 个小时挖掘参考资料 了解强与弱的关系ARC https developer apple com
  • 如何从 ContentView 外部显示 SwiftUI 警报?

    我正在构建 Swift 应用程序 并试图找出如何显示警报 我有一个单独的 swift 文件正在执行一些计算 并且在某些条件下我希望它向用户显示警报 基本上告诉他们出了问题 然而 我见过的大多数例子都要求警报在ContentView或以其他方
  • 如何制作带有 SWIFT 图像的弹出窗口

    我想知道如何制作类似于此示例的弹出窗口 原始窗口充满了按钮 选择这些按钮后将拉出我想要使用的图像 我会简单地创建一个可重用的UIView组件以及作为子视图所需的一切 例如UIImageView为了你的形象 UILabel or a UIBu
  • 有关 Swift 编译器选项的文档

    您好 我想开始在 Apple Swift 语言上运行一些微基准测试 然而 我觉得很难找到有关编译器优化的不同选项的适当文档 我读过很多关于其他人的语言微基准的问题和文章 但是如果能有一些关于该主题的可靠文档那就太好了 在最新的测试版中 使用
  • ios swift parse:从 3 个类收集数据

    我有这样的结构 User CardSet 带有指向 User objectId 的指针 user 和 col name 带有点 cards 的卡片到 Card Set objectId 和列 name 我想选择所有卡数据 包括当前用户的卡集
  • 如何在 Swift 中从 UIColor 获取 RGB 代码(INT)[重复]

    这个问题在这里已经有答案了 我想在 Swift 中获取 UIColor 的 RGB 值 let swiftColor UIColor red 1 green 165 255 blue 0 alpha 1 println RGB Value
  • Swift - 元类型 .Type 和 .self 之间有什么区别?

    元类型有什么区别 Type and self在斯威夫特 Do self and Type返回一个struct 我明白那个 self可以用来检查dynamicType 你如何使用 Type 首先也是最重要的是查看 Apple 文档type o
  • “预期的 ';'在 Swift 下的顶级声明符之后”

    我正在尝试将所有颜色设置在一个 Swift 文件中 该文件可以在我的整个应用程序中使用 下面的代码会导致 import Foundation import UIKit class DotColors let tsblueColor UICo
  • UIView 圆角 - Swift 2.0?

    我会尝试将一些项目更新到 Swift 2 0 我有一个视图 左上角有一个圆角 在 Swift 没有警告 没有错误 只是没有圆角 这就是它在 Swift let maskPath UIBezierPath roundedRect conten
  • iPhone 上的纵向 UISplitViewController 在 iOS 8 中始终显示主视图和细节视图

    UISplitViewController in portrait在 iPhone 上始终显示主控和细节iOS 8 我尝试子类化UISplitViewController并将其配置为同时显示主视图和细节视图 但没有任何效果 class AP
  • 在 Swift 中有条件导入基于 iOS 版本的框架(如 Speech)?

    有没有办法有条件地导入框架Swift基于运行时 iOS 版本 特别是 我有一个部署目标为的应用程序iOS 8 我想使用新的Apple Speech应用程序中的框架 如果在运行时可用 我知道 available iOS 10 代码部分的指令
  • SwiftUI DisclosureGroup 单独展开每个部分

    我正在使用 Foreach 和 DisclosureGroup 来显示数据 每个部分都可以展开 折叠 然而 它们都在同时扩展 折叠 如何单独展开 折叠每个部分 struct TasksTabView View State private v
  • 类继承通用字典和Interface

    我有一个继承通用字典和接口的类 public class MyDictionary Dictionary
  • iOS9 Swift 文件使用 NSURL 创建 NSFileManager.createDirectoryAtPath

    在iOS9之前 我们创建了一个像这样的目录 let documentsPath NSSearchPathForDirectoriesInDomains DocumentDirectory UserDomainMask true 0 as S
  • RealityKit – 从中心缩放模型

    我想就地缩放 3D 模型 一个高大的玩具机器人 即从其中心开始 它应该在所有维度上增大和缩小 而不改变位置 我可以缩放玩具机器人模型 但该模型从其脚部开始放大或缩小 而不是其正确的中心 我尝试过通过缩放model scale 我也尝试过使用
  • UnsafeMutablePointer 到具体对象类型

    我怎样才能从UnsafeMutablePointer

随机推荐