问题标签 [generic-variance]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
1227 浏览

generics - 我该如何处理这个“这不是被覆盖的子类型”错误

我正在尝试在 Kotlin 中编写一些可验证的表单界面。在验证部分我使用https://github.com/kamedon/Validation

这是我要运行的非常简单的代码;

这段代码给了我;

如果我Validation<out Any>在 Validatable 中使用它会说;

如果我Validation<in Any>在 Validatable 中使用它会说;

如果我使用Validation<Any>而不是Validation<LoginForm>在 LoginForm 中,代码会运行,但这次内部的名称和年龄validation是从内部的类中使用的。关于图书馆的使用,我不想改变这一点。

反正有没有一起使用inout关键字,或者可能有另一种方法来实现我的目标。

0 投票
2 回答
218 浏览

scala - Scala List map 函数的变化

我有一个问题一直困扰着我。Scala 中的列表是协变的 ( List[+A])

假设我们有这些类:

map函数取List[B]函数f: B => C

但我也可以使用 af: A => C 它的子类,f: B => C
它完全有意义。

我目前感到困惑的是,该map函数应该只接受作为原始函数超类的函数(因为函数的参数是逆变的),这不适用于我给出的示例。

我知道我的逻辑有问题,我想开导。

0 投票
2 回答
6207 浏览

kotlin - Kotlin:返回数组如果 E 是实现接口 I 的枚举类,则从返回类型为 Array 的函数

0 投票
2 回答
327 浏览

c# - .net 核心中的逆变性如何与 Func 委托一起使用

我有以下代码,我正在尝试为我的域对象编写通用验证规则。在这样做的同时,我有一个问题来处理 Func 代表支持差异

使用上面的代码,编译器会给出一条错误消息说

在线编译器错误:base.AddValidationRule(empPredicate); 参数 1:无法从 'System.Func<>Employee, bool>' 转换为 'System.Func<>Person, bool>

我曾参考过此https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/dd465122%28v%3dvs.100%29但我仍然无法使编译器了解这里的逆变,

感谢您的帮助,以便我更好地理解这一点

0 投票
2 回答
223 浏览

scala - 使用扩展方法规避差异检查

这不编译:

好吧,够公平的。但这确实编译:

这让我们可以规避方差检查给我们带来的任何问题:

这感觉像是在作弊。应该避免吗?或者编译器让它滑动有什么正当理由吗?

更新:

考虑一下这个例子:

显然我们已经设法实现了不可能的目标:仍然满足A => Boolean. 但如果这是不可能的,编译器不应该禁止它吗?

0 投票
1 回答
160 浏览

generics - Kotlin 泛型:违反直觉的类型推断和使用 out 关键字检查

我最近一直在学习 Kotlin,同时对协变类型有一些疑问。

示例代码在这里。我有Option并且Option2都有一个类型参数T和一个run扩展名。

我可以理解 中的前两个runvalidation()因为它们的行为类似于 Java。但是为什么第三行编译?Option<T>在 中是不变T。我们不能将Option<C>实例传递到Option<B>预期的位置。

在我添加一个out关键字之后T,现在它们都可以编译了。为什么?

0 投票
3 回答
114 浏览

c# - 如何使用受约束的泛型类型参数将类实例化为其派生的接口

以下接口定义了一个数据包。

有两个实现,每个都有自己的附加属性。

以上是我无法控制的库代码。我想为数据包创建一个处理程序

并为具体数据包创建两个实现。

我想将数据包处理程序列表注入到管理数据包处理的类中,以便将来可以使用其他数据包处理程序对其进行扩展。

我遇到的麻烦是在创建注入参数时。我不能做

因为我不能像这样创建一个实例:

我得到错误Cannot implicitly convert type 'FooPacketHandler' to 'IPacketHandler<IPacket>. An explicit conversion exists (are you missing a cast?)

我看了一个类似的问题:Casting generic type with interface constraint。在那个问题中,OP 没有显示接口的成员,只是从泛型的角度来定义它。据我所见,如果我的接口没有使用泛型类型参数作为输入,我可以使用out关键字使其成为协变的,但这不适用于此处。

如何做到让管理者坚持开闭原则?我唯一的办法是将接口定义更改为

然后在实现中转换为特定的数据包?

0 投票
1 回答
59 浏览

c# - 我的协变泛型参数的解决方法是必要的吗?

我从一个简单的通用接口开始:

但是我需要使这个接口的泛型类型协变(出于我不会讨论的原因),但这会导致编译器错误,因为Func<T0,TReturn>需要T0逆变(in T0)或不变参数:

所以我得到这个DoSomething声明的编译器错误:

错误 CS1961 变化无效:类型参数“TObject”必须在“ IFooContext<TObject>.DoSomething<TValue>(Expression<Func<TObject, TValue>>)”上始终有效。'TObject' 是协变的。

在向墙上抛出各种想法后,我发现我可以通过移动DoSomething到非泛型接口并 TObject在方法上指定其参数来解决此问题,然后将最初预期的方法“公开”为扩展方法,如下所示:

这编译和运行没有任何问题 - 实际用法的语法与我之前示例的预期用法相同。

为什么这行得通,为什么 C# 编译器不能用我原来的单一协变泛型接口在内部为我做这个技巧?

0 投票
0 回答
101 浏览

scala - 对于具有类型绑定的逆变类型,隐式解析失败

以下代码编译:

当我们制作T协变 ( class X[U, +T <: U]) 时,它也会编译:

当我们制作T逆变(class X[U, -T <: U])时,编译器无法实现implicitly[X[String, String]]。奇怪的是,它能够实现implicitly[X[Any, Any]]

我怀疑尽管有明确的类型注释,但 typeT处于逆变位置,过早地固定为Any. 这是预期的行为吗?

奖励点:T如果我们修复,逆变确实有效U

UPDATE1:Dmytro Mitin 回复后更新:

0 投票
1 回答
61 浏览

scala - 类型参数化、方差与继承基类的使用

我有一个关于在 Scala 中定义方法/类时何时使用类型参数化与基类类型的问题,特别是当允许的类型在同一层次结构中时 - 使用类型绑定进行约束。

例如:

在上述情况下/通常当将允许的类型限制在某个上限时,我会获得什么优势,NewType反之亦然NewTypeV2?他们看起来都和我一样。

据我了解,如果我要添加一些隐式条件检查,例如NewType[T: Addable]存在于不同层次结构的类型中,那么类型参数化将是有意义的,除了我应该更喜欢类型参数化而不是使用接口类型或基类类型(如案例类成员inTypeA的类型。NewTypeV2

像 NewType[T] 这样定义类型参数化的方式是否被认为比其他方式更“功能性”?

其次,关于方差与类型界限的问题。在上面的代码块中,NewType 在 Type T 上是不变的,所以 NewType[SubTypeA1] 不是 NewType[TypeA] 的子类型,它们是不相关的,对吗?

如果如上所述我对类型不变性的理解是正确的,那么 testMethod1 是如何编译的?因为我明确地传递了 SubTypeA1 但它仍然被转换为 NewType[TypeA] 并且它可以毫无问题地传递给 testMethod2 。我在这里有什么误解?