- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用 Signals图书馆。
假设我定义了 BaseProtocol 协议(protocol)和 ChildClass
符合 BaseProtocol
.
protocol BaseProtocol {}
class ChildClass: BaseProtocol {}
var signals: Array<Signal<BaseProtocol>> = []
let signalOfChild = Signal<ChildClass>()
signals.append(signalOfChild)
var arrays = Array<Array<BaseProtocol>>()
let arrayOfChild = Array<ChildClass>()
arrays.append(arrayOfChild)
最佳答案
区别在于 Array
(和 Set
和 Dictionary
)从编译器得到特殊处理,允许协方差(我更详细地讨论了这个 in this Q&A )。
然而,任意泛型类型是 invariant , 表示 X<T>
是与 X<U>
完全无关的类型如果 T != U
– T
之间的任何其他类型关系和 U
(例如子类型)是无关紧要的。适用于您的案例,Signal<ChildClass>
和 Signal<BaseProtocol>
是不相关的类型,即使 ChildClass
是 BaseProtocol
的子类型(另见 this Q&A)。
原因之一是它会完全破坏定义与 T
相关的逆变事物(例如函数参数和属性 setter )的通用引用类型。 .
例如,如果您实现了 Signal
作为:
class Signal<T> {
var t: T
init(t: T) {
self.t = t
}
}
let signalInt = Signal(t: 5)
let signalAny: Signal<Any> = signalInt
signalAny.t = "wassup" // assigning a String to a Signal<Int>'s `t` property.
String
到
Int
属性(property)。
Array
来说是安全的是它是一个值类型 - 因此当你这样做时:
let intArray = [2, 3, 4]
var anyArray : [Any] = intArray
anyArray.append("wassup")
anyArray
是
intArray
的副本– 因此
append(_:)
的逆变性不是问题。
protocol BaseProtocol {}
class ChildClass: BaseProtocol {}
class AnotherChild : BaseProtocol {}
class Signal<T> {
var t: T
init(t: T) {
self.t = t
}
}
let childSignal = Signal(t: ChildClass())
let anotherSignal = Signal(t: AnotherChild())
Signal<T>
T
的实例符合
BaseProtocol
可能看起来像这样:
struct AnyBaseProtocolSignal {
private let _t: () -> BaseProtocol
var t: BaseProtocol { return _t() }
init<T : BaseProtocol>(_ base: Signal<T>) {
_t = { base.t }
}
}
// ...
let signals = [AnyBaseProtocolSignal(childSignal), AnyBaseProtocolSignal(anotherSignal)]
Signal
的异构类型。
T
是某种符合
BaseProtocol
的类型.
BaseProtocol
的范围内。 .如果我们有
AnotherProtocol
并想要
Signal
的类型橡皮擦
T
的实例符合
AnotherProtocol
?
transform
类型橡皮擦的函数,允许我们执行任意向上转换。
struct AnySignal<T> {
private let _t: () -> T
var t: T { return _t() }
init<U>(_ base: Signal<U>, transform: @escaping (U) -> T) {
_t = { transform(base.t) }
}
}
Signal
的异构类型。在哪里
T
是某种可转换为
U
的类型,这是在创建类型橡皮擦时指定的。
let signals: [AnySignal<BaseProtocol>] = [
AnySignal(childSignal, transform: { $0 }),
AnySignal(anotherSignal, transform: { $0 })
// or AnySignal(childSignal, transform: { $0 as BaseProtocol })
// to be explicit.
]
transform
每个初始化器的函数有点笨拙。
BaseProtocol
定义自己的初始化程序来减轻调用者的负担。在扩展中:
extension AnySignal where T == BaseProtocol {
init<U : BaseProtocol>(_ base: Signal<U>) {
self.init(base, transform: { $0 })
}
}
let signals: [AnySignal<BaseProtocol>] = [
AnySignal(childSignal),
AnySignal(anotherSignal)
]
[AnySignal<BaseProtocol>]
- 但如果您要允许更多方便的初始化器,我会保持显式)
Signal<T>
的转换。 (其中
T
符合
BaseProtocol
)到
Signal<BaseProtocol>
.
Signal
的扩展中定义一个(方便的)初始化程序来做到这一点。
T == BaseProtocol
的类型:
extension Signal where T == BaseProtocol {
convenience init<T : BaseProtocol>(other: Signal<T>) {
self.init(t: other.t)
}
}
// ...
let signals: [Signal<BaseProtocol>] = [
Signal(other: childSignal),
Signal(other: anotherSignal)
]
extension Signal where T : BaseProtocol {
func asBaseProtocol() -> Signal<BaseProtocol> {
return Signal<BaseProtocol>(t: t)
}
}
// ...
let signals: [Signal<BaseProtocol>] = [
childSignal.asBaseProtocol(),
anotherSignal.asBaseProtocol()
]
struct
,这两种情况下的过程相似。 .
关于Swift泛型强制的误解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56757847/
所以我实际上正在阅读有关用于删除对象属性的“delete”方法的文档,并且我偶然发现了这个“此外,您不能删除使用 var 关键字声明的全局对象的属性。” 所以我真正理解的是:假设你创建了一个数组: v
我目前正在学习 Javascript,我想知道为什么下面的代码会执行“console.log('why')”。我认为“变量”(var、let、const)仅存储信息,不能自行执行。我不希望以下内容实际
在许多博客和引用文献中,我读到了有关冲洗刷新记录的信息,其中有很多信息会引起头痛和一些误解: 是否为复制的碎片保留了事务日志?为什么? 如果GET /_cat/allocation包含转记录? 超过磁
我有下一个循环: rolling_average_delta_follower=[]; followers=[32,34,36,38,40,42,44,46,48,50,52,54,5
我遇到了多处理问题;我在 linux 2.6.36 上使用 python2.7。我知道使用更高级别的模块或库会容易得多,但我正在尝试使用较低级别的函数(os.fork() 和 os.exec*)以确保
有人可以向我解释一下,为什么这段代码不起作用。我正在浏览周围的一些问题,但找不到答案。可能是因为(大量)缺乏知识。 感谢您提供的任何帮助。 char** sentence = malloc(min);
我的目标是我想用一些 java 代码登录到一个站点,并在登录后做一些工作。(为了编写一些 java cooking 处理,我首先需要了解这一切实际上是如何工作的)问题是我不太清楚如何管理 cookie
给定以下非常简单的结构: struct A { int a; double b; }; (使用 Mac OS 10.9 - Xcode) 结构的大小是 16。我不明白为什么。为什么不是
我刚刚下载了基于 ASP.NET 5 的 music store (microsoft sample projct) 源代码。我不明白为什么 Microsoft 的开发人员在 Controller 中
Closed. This question is not reproducible or was caused by typos。它当前不接受答案。 想改善这个问题吗?更新问题,以便将其作为on-to
我正在阅读 this doc并看到以下片段: The := syntax is shorthand for declaring and initializing a variable, e.g. fo
我在理解描述的 MixColumns 步骤时遇到问题 here . 我知道扩散,这一切都是有道理的,因为它指出每列都被视为多项式并乘以 GF(2^8) 的模。 但是..乘以GF(2 ^ 8)。尽管域仍
我尝试自定义HTML文件输入并编写了最简单的jquery API函数: (function($) { $.fn.selectFileInputGUI = function() {
我对 SSL/TLS 有一个根本性的误解,希望能得到澄清。 按照我的理解,当我获得网站证书时,它包含我的所有信息,并由我的证书颁发机构(VeriSign 或其他任何人)签名。当有人从我的网站请求使用
我们在代码中有一个 NamedTuple,如下所示: from typing import NamedTuple class StandardParameters(NamedTuple): o
我有一个问题,我需要你的帮助: 我正在制作一个 Web 应用程序来访问我需要在类似( ListView 或 DataList )这样的工具中显示他们的员工列表,以直接绑定(bind)数据库中的数据,并
我知道根是: 静态字段 方法参数 本地领域 f-queue 也包含一个指向“将要完成的”对象的指针 cpu 寄存器 <=??? 现在让我们谈谈寄存器。 它们可以包含的代码如下: mov bx, 003
官方例子Timer组件使用this.interval var Timer = React.createClass({ getInitialState: function() { retur
使用 PostGIS 我有两个表,第一个包含 250 个城市的边界,第二个包含世界上所有国家/地区的边界。 我试图影响每个城市所属的国家/地区。下面的查询可以让我得到我想要的结果。 SELECT DI
我正在准备数据库和 SQL 考试,并且正在解决一个练习: 我们有一个包含 4 个表的数据库,代表一家人力资源公司。这些表格是: applicant(a-id,a-name,a-city,years-
我是一名优秀的程序员,十分优秀!