我有结构向量:
struct Vector{
var X : Measurement<Dimension>
var Y : Measurement<Dimension>
var Z : Measurement<Dimension>
...我创建了新的对象,例如:
let test = Measurement(value: 1.5, unit: UnitLength.inches) as Measurement<Dimension>
var lVector = Vector(x: Measurement(value: 10, unit: UnitLength.meters), y: test, z: Measurement(value: 10, unit: UnitLength.meters))一切都很好。但是,如果尝试使用其他类中的变量,则会出现以下错误:“无法将类型‘测量’的值转换为强制情况下的‘测量’类型”。
final class SettingsManager{
...
var test = Measurement(value: 1.5, unit: UnitLength.inches)
... }
class Calculator {
...
let test = SettingsManager.shared.test as Measurement<Dimension>
var lVector = Vector(x: Measurement(value: 10, unit: UnitLength.meters), y: test, z: Measurement(value: 10, unit: UnitLength.meters))我试过“作为!”并得到了
Cast from 'Measurement<UnitLength>'
to unrelated type 'Measurement<Dimension>'
always fails在这个类中声明的相同变量可以正常工作,就像我在上面展示的那样。我做错了什么?
发布于 2022-02-02 12:36:18
Measurement<UnitLength>不是Measurement<Dimension>的一种。这些都是不相关的类型。它只在这里起作用:
let test = Measurement(value: 1.5, unit: UnitLength.inches) as Measurement<Dimension>
var lVector = Vector(x: Measurement(value: 10, unit: UnitLength.meters), y: test, z: Measurement(value: 10, unit: UnitLength.meters))因为这里的Measurement(...)调用实际上是在创建Measurement<Dimension>,因为这正是调用站点所期望的。as Measurement<Dimension>告诉它您需要一个Measurement<Dimension>,而x和z的参数类型也是Measurement<Dimension>。类型推断算法足够聪明,可以看出您也必须是指Measurement<Dimension>(...)。
Measurement<Dimension>.init将一个Dimension作为它的第二个参数,而UnitLength是该参数的一个子类型,因此没有问题。
另一方面,在SettingsManager中,您这样声明test:
var test = Measurement(value: 1.5, unit: UnitLength.inches)这里没有提到Measurement<Dimension>,所以类型推断算法只使用第二个参数来推断您必须指的是Measurement<UnitLength>,所以test的类型是Measurement<UnitLength>。
如果您只是添加as Measurement<Dimension>
var test = Measurement(value: 1.5, unit: UnitLength.inches) as Measurement<Dimension>应该管用的。
然而,如果向量的所有三个组件都有相同类型的单位,难道不是更有意义吗?
struct Vector<T: Dimension>{
var X : Measurement<T>
var Y : Measurement<T>
var Z : Measurement<T>
}发布于 2022-02-02 13:57:58
这只是为了解决为什么这是合法的问题:
let test = Measurement(value: 1.5, unit: UnitLength.inches) as Measurement<Dimension>
var lVector = Vector(x: Measurement(value: 10, unit: UnitLength.meters), y: test, z: Measurement(value: 10, unit: UnitLength.meters))这甚至不应该是一个问题,这只是正常的替代原则。让我们用一种简单的方式来表达它。如果你不投呢?
let test = Measurement(value: 1.5, unit: UnitLength.inches)然后test被推断为Measurement<UnitLength>。现在让我们开始:
let test: Measurement<Dimension> = Measurement(value: 1.5, unit: UnitLength.inches)这是合法的。为什么?这并不是因为Measurement<UnitLength>是Measurement<Dimension>的一个子类型。不是的!这是因为UnitLength是维度的一个子类型。就好像你说过
let test = Measurement(value: 1.5, unit: UnitLength.inches as Dimension)你看到了吗?实际上,您并没有将Measurement<UnitLength>转换为Measurement<Dimension>;这是不可能的。您将UnitLength转换到维度,这是完全可能的。这和你说的没什么不同
let test2: Dimension = UnitLength.inches您总是可以在需要超级类型的地方替换子类型。最初问题的难点在于Measurement<UnitLength>不是Measurement<Dimension>的子类型(因为Swift泛型不会在参数化类型上自动协变)。
发布于 2022-02-02 12:31:41
当您在test中声明SettingsManager变量时,您没有显式地提到一个类型。因此,斯威夫特的类型推理算法决定了变量的类型取决于Measurement(...)中的第二个参数。
在本例中,test具有Measurement<UnitLength>类型。如果您使用传递的UnitArea.acres作为第二个参数,您的变量将具有Measurement<UnitArea>类型。不是Measurement<Dimension>。
如果您首先以Measurement<Dimension>的形式显式地提到该类型,它将解决这个问题。
var test : Measurement<Dimension> = Measurement(value: 1.5, unit: UnitLength.inches)现在让我们检查一下为什么你的铸造失败。您可以将类型转换为它的子类型或超级类型。UnitLength是Dimension的一个子类型。这样你就可以在他们中间投了。
但是Measurement<UnitLength>是而不是,是Measurement<Dimension>的一个子类型。为什么?
原因很简单。泛型是不变的。这意味着,即使泛型类型包装了一个子类型,它也不会使它成为包装其超类的泛型的子类型。
有关上述段落的更多说明,请阅读这。
https://stackoverflow.com/questions/70955451
复制相似问题