问题标签 [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 投票
2 回答
373 浏览

scala - Scala - 返回与作为参数传递的相同类型

假设我有一个 A、B、C 类继承的 M 类:

我想做这样的事情:

Wheretransform对每个子类型基本上都是一样的,只是结果对象的构造方式不同。

我有一种不可能的预感,我需要复制代码并创建单独的转换方法或求助于类型转换。或者,还有更好的方法?

编辑

请注意,def transform[T<:M](t:T):T这不起作用。如果我们尝试返回 A、B 或 C,我们将收到以下错误消息。

A 类型的表达式不符合预期的 T 类型

B 类型的表达式不符合预期的 T 类型

C 类型的表达式不符合预期的 T 类型

编辑 2 也许关于我正在尝试做的一些更详细的信息:

如果我这样做,那么我需要演员表:

我想消除它。

0 投票
1 回答
117 浏览

c# - 访问泛型参数的泛型参数?

我很难解决 C# 中的问题。

在我正在处理的项目中,有一些consumable类存储信息,还有一些consumer类使用这些消耗类。

我以更简单的方式复制了这个东西:

这完全正常。但是,我也希望有一些middle消费者,它们consumer在其构造函数(或另一个方法)中采用另一个对象,它将 Feed 调用重定向到对象。例如:

我会这样使用它:

但我将MiddleConsumer与其他具体Consumer类一起使用,例如BaseConsumerDerivedConsumer。因此我不必T显式指定参数,它可以从实际Consumer的 s 类型中获取它。让我澄清一下。我想要这样的东西:(注意这不是有效的 C# 代码)

但是, - 正如预期的那样 - 由于具有那个奇怪的通用参数,这不起作用。

我希望能够使用我不知道其基本类型的 Consumer 创建一个 MiddleConsumer 对象。我的意思是,我希望能够做到这一点:

我不想BaseConsumer每次使用 with 时都检查 -for example- 的基本类型,因为当我使用withMiddleConsumer时编译器只能查看它。请注意,可能有几十个不同的类。ConsumerMiddleConsumerConsumer

我的问题是:有没有办法让 C# 编译器MiddleConsumer从它的泛型参数中推断出可消耗的类型?

谢谢您的帮助!

0 投票
1 回答
415 浏览

scala - Scala协方差和下界我不明白

我目前正在学习scala,我对方差注释特别是协方差逆变感到困惑。

所以我做了一些研究,发现了下面的例子

所以这表示 Box 类在 T 中是协变的,这意味着 Box[Cat] 是 Box[Animal] 的子类,因为 Cat 是 Animal 的子类。到目前为止我明白这一点。但是当谈到方法参数时,我的理解就结束了。规范说方法参数不能是协变的,所以我们必须使用这个下限注释。

让我们看看方法定义

所以 [U >: T] 说 U 必须是 T 的超类

尝试以下代码

按预期工作,但这让我发疯

从逻辑上讲,将INT放入 Box of Animals对我来说毫无意义,因为它是正确的,因为INT将被解析为Any,它是Animal的超类。

所以我的问题是

我如何调整put method只接受动物子类型的代码?我不能使用上限注释

因为我得到了这个众所周知的错误

协变类型 T 出现在类型中的逆变位置

0 投票
2 回答
85 浏览

scala - scala 类型绑定符号方向有区别吗?

scala 类型绑定符号方向是否存在差异,因为[B <: A]与 相同[A >: B]

0 投票
1 回答
101 浏览

c# - 在不违反空接口规则的情况下创建协变泛型类型

背景:我想“扩展”.NET类型以支持与基础对象Lazy<>之间的隐式转换,以便能够自动解包包含的值。我能够很容易地做到这一点:Lazy<T>T

我想通过使协变更进一步,T这样我就可以分配ExtendedLazy<Derived>to的实例ExtendedLazy<Base>。由于类定义中不允许使用方差修饰符,我不得不求助于一个空接口来实现这一点:

并将我的类定义更改为

public class ExtendedLazy<T> : Lazy<T>, IExtendedLazy<T>

这工作正常,我能够使用这种协变类型:

虽然这编译和工作正常,但它违反了CA1040:避免空接口,它说使用空接口作为合同是一种糟糕的设计和代码味道(我相信大多数人都同意)。我的问题是,鉴于 CLR 无法识别类定义中的变体泛型类型,还有哪些其他方法可以使其与可接受的 OO 实践更加一致?我想我不是唯一面临这个问题的人,所以希望能对此有所了解。

0 投票
1 回答
58 浏览

scala - 如何编写一个在scala中接受具有协变或逆变约束的参数的方法?

我正在编写一个 scala 程序,它在某些时候应该为某些任务提供一些状态更新,它也可以为任务组提供它。关键是在不同phase的s中,细节是不同的。所以实际上这个Detailstrait 有多种实现方式,这里我没有包括在内。

现在,问题是接收此状态更新的方法,我无法正确签名。如果我只是把def receiveStatus(status: StatusMessage)编译器抱怨说StatusMessage接受类型参数。我以为我需要类似的东西,def receiveStatus[S :> Details](status: StatusMessage[S])但这也不能编译。

0 投票
0 回答
577 浏览

scala - Scala 函数中的方差(协方差和逆变)

我正在使用 Scala 研究 FP 概念。我想我终于明白了什么是协变和逆变,以及为什么函数类型的参数类型是逆变的,而它们的返回类型是协变的。但仍有一些我不明白的地方。在 Scala 中, aList[+A]有一个 prepend( +:) 方法,它接受Swhere S >: A。如果类型是 an A,编译器会抛出一个错误:协变参数在逆变位置,我不明白为什么声明 a 的事实在函数定义中使协变List[+A]A据我了解,协变和逆变涉及比 更复杂的类型A,即单子或函数。

斯卡拉列表:http ://www.scala-lang.org/api/current/index.html#scala.collection.immutable.List

0 投票
3 回答
412 浏览

c# - 与 Func 的协/逆变作为参数

假设我有一个界面,例如

TIn逆变的,并且TOut变的。

现在,我希望调用者能够指定要对输入值执行的某些函数,所以我会天真地将以下方法添加到接口中:

这……不起作用。TIn现在要求是协变和TOut逆变的。

我明白,我不能使用协变泛型类型作为方法的输入,但我认为我可以在嵌套泛型类型中使用它们,该类型本身指定方差(Func<in T1, out TResult>)。

我尝试使用协变/逆变类型创建一个新的委托类型,并将接口更改为接受这种类型的参数,但无济于事(同样的错误)。

我有办法让编译器开心吗?这甚至可能吗(例如使用其他嵌套类型或其他泛型参数)?如果不是,为什么不呢?

0 投票
3 回答
697 浏览

c# - 为什么类类型参数的方差必须与其方法的返回/参数类型参数的方差相匹配?

以下引起投诉:

但我无法想象这在哪里不是类型安全的。(snip*) 这是不允许这样做的原因,还是有其他一些我不知道的违反类型安全的情况?


* 诚然,我最初的想法令人费解,但尽管如此,反应非常彻底,@Theodoros Chatzigiannakis甚至以令人印象深刻的准确度剖析了我最初的假设。

回想起来,除了一个很好的耳光外,我意识到我错误地假设当它被分配给ICovariant::Ma 时,它的类型签名仍然是 a 。然后,将其分配给来自 看起来不错,但当然是非法的。为什么不直接禁止最后一个明显非法的演员阵容?(所以我认为)Func<IInvariant<Derived>>ICovariant<Derived>ICovariant<Base>MFunc<IInvariant<Base>>ICovariant<Base>

正如埃里克·利珀特( Eric Lippert)也指出的那样,我觉得这种错误的和切线的猜测会削弱这个问题,但出于历史目的,被剪断的部分:

对我来说最直观的解释是,以ICovariant协变为例,TCov意味着该方法IInvariant<TCov> M()可以强制转换为某个IInvariant<TSuper> M()where TSuper super TCov,这违反了TInvin的不变性IInvariant。然而,这种暗示似乎没有必要:通过IInvariant禁止.TInvM

0 投票
1 回答
755 浏览

function - Kotlin:混淆 lambda 和泛型

请在评论中查看错误消息:

关键点:

  • bookPrint()并且authorPrint()都需要一本空书/作者
  • printIt()需要采取其中任何一个功能。

所以,考虑“生产者扩展,消费者超级”我认为我的问题是我希望输入参数是协变的,当它被硬编码为逆变(“in”)时。

我有这个想法没有奏效: