问题标签 [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.
scala - Scala - 返回与作为参数传递的相同类型
假设我有一个 A、B、C 类继承的 M 类:
我想做这样的事情:
Wheretransform
对每个子类型基本上都是一样的,只是结果对象的构造方式不同。
我有一种不可能的预感,我需要复制代码并创建单独的转换方法或求助于类型转换。或者,还有更好的方法?
编辑
请注意,def transform[T<:M](t:T):T
这不起作用。如果我们尝试返回 A、B 或 C,我们将收到以下错误消息。
A 类型的表达式不符合预期的 T 类型
B 类型的表达式不符合预期的 T 类型
C 类型的表达式不符合预期的 T 类型
编辑 2 也许关于我正在尝试做的一些更详细的信息:
如果我这样做,那么我需要演员表:
我想消除它。
c# - 访问泛型参数的泛型参数?
我很难解决 C# 中的问题。
在我正在处理的项目中,有一些consumable
类存储信息,还有一些consumer
类使用这些消耗类。
我以更简单的方式复制了这个东西:
这完全正常。但是,我也希望有一些middle
消费者,它们consumer
在其构造函数(或另一个方法)中采用另一个对象,它将 Feed 调用重定向到对象。例如:
我会这样使用它:
但我将MiddleConsumer
与其他具体Consumer
类一起使用,例如BaseConsumer
和DerivedConsumer
。因此我不必T
显式指定参数,它可以从实际Consumer
的 s 类型中获取它。让我澄清一下。我想要这样的东西:(注意这不是有效的 C# 代码)
但是, - 正如预期的那样 - 由于具有那个奇怪的通用参数,这不起作用。
我希望能够使用我不知道其基本类型的 Consumer 创建一个 MiddleConsumer 对象。我的意思是,我希望能够做到这一点:
我不想BaseConsumer
每次使用 with 时都检查 -for example- 的基本类型,因为当我使用withMiddleConsumer
时编译器只能查看它。请注意,可能有几十个不同的类。Consumer
MiddleConsumer
Consumer
我的问题是:有没有办法让 C# 编译器MiddleConsumer
从它的泛型参数中推断出可消耗的类型?
谢谢您的帮助!
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 出现在类型中的逆变位置
scala - scala 类型绑定符号方向有区别吗?
scala 类型绑定符号方向是否存在差异,因为[B <: A]
与 相同[A >: B]
?
c# - 在不违反空接口规则的情况下创建协变泛型类型
背景:我想“扩展”.NET类型以支持与基础对象Lazy<>
之间的隐式转换,以便能够自动解包包含的值。我能够很容易地做到这一点:Lazy<T>
T
我想通过使协变更进一步,T
这样我就可以分配ExtendedLazy<Derived>
to的实例ExtendedLazy<Base>
。由于类定义中不允许使用方差修饰符,我不得不求助于一个空接口来实现这一点:
并将我的类定义更改为
public class ExtendedLazy<T> : Lazy<T>, IExtendedLazy<T>
这工作正常,我能够使用这种协变类型:
虽然这编译和工作正常,但它违反了CA1040:避免空接口,它说使用空接口作为合同是一种糟糕的设计和代码味道(我相信大多数人都同意)。我的问题是,鉴于 CLR 无法识别类定义中的变体泛型类型,还有哪些其他方法可以使其与可接受的 OO 实践更加一致?我想我不是唯一面临这个问题的人,所以希望能对此有所了解。
scala - 如何编写一个在scala中接受具有协变或逆变约束的参数的方法?
我正在编写一个 scala 程序,它在某些时候应该为某些任务提供一些状态更新,它也可以为任务组提供它。关键是在不同phase
的s中,细节是不同的。所以实际上这个Details
trait 有多种实现方式,这里我没有包括在内。
现在,问题是接收此状态更新的方法,我无法正确签名。如果我只是把def receiveStatus(status: StatusMessage)
编译器抱怨说StatusMessage
接受类型参数。我以为我需要类似的东西,def receiveStatus[S :> Details](status: StatusMessage[S])
但这也不能编译。
scala - Scala 函数中的方差(协方差和逆变)
我正在使用 Scala 研究 FP 概念。我想我终于明白了什么是协变和逆变,以及为什么函数类型的参数类型是逆变的,而它们的返回类型是协变的。但仍有一些我不明白的地方。在 Scala 中, aList[+A]
有一个 prepend( +:
) 方法,它接受S
where S >: A
。如果类型是 an A
,编译器会抛出一个错误:协变参数在逆变位置,我不明白为什么声明 a 的事实在函数定义中使协变List[+A]
。A
据我了解,协变和逆变涉及比 更复杂的类型A
,即单子或函数。
斯卡拉列表:http ://www.scala-lang.org/api/current/index.html#scala.collection.immutable.List
c# - 与 Func 的协/逆变作为参数
假设我有一个界面,例如
TIn
是逆变的,并且TOut
是协变的。
现在,我希望调用者能够指定要对输入值执行的某些函数,所以我会天真地将以下方法添加到接口中:
这……不起作用。TIn
现在要求是协变和TOut
逆变的。
我明白,我不能使用协变泛型类型作为方法的输入,但我认为我可以在嵌套泛型类型中使用它们,该类型本身指定方差(Func<in T1, out TResult>
)。
我尝试使用协变/逆变类型创建一个新的委托类型,并将接口更改为接受这种类型的参数,但无济于事(同样的错误)。
我有办法让编译器开心吗?这甚至可能吗(例如使用其他嵌套类型或其他泛型参数)?如果不是,为什么不呢?
c# - 为什么类类型参数的方差必须与其方法的返回/参数类型参数的方差相匹配?
以下引起投诉:
但我无法想象这在哪里不是类型安全的。(snip*) 这是不允许这样做的原因,还是有其他一些我不知道的违反类型安全的情况?
* 诚然,我最初的想法令人费解,但尽管如此,反应非常彻底,@Theodoros Chatzigiannakis甚至以令人印象深刻的准确度剖析了我最初的假设。
回想起来,除了一个很好的耳光外,我意识到我错误地假设当它被分配给ICovariant::M
a 时,它的类型签名仍然是 a 。然后,将其分配给来自 看起来不错,但当然是非法的。为什么不直接禁止最后一个明显非法的演员阵容?(所以我认为)Func<IInvariant<Derived>>
ICovariant<Derived>
ICovariant<Base>
M
Func<IInvariant<Base>>
ICovariant<Base>
正如埃里克·利珀特( Eric Lippert)也指出的那样,我觉得这种错误的和切线的猜测会削弱这个问题,但出于历史目的,被剪断的部分:
对我来说最直观的解释是,以
ICovariant
协变为例,TCov
意味着该方法IInvariant<TCov> M()
可以强制转换为某个IInvariant<TSuper> M()
whereTSuper super TCov
,这违反了TInv
in的不变性IInvariant
。然而,这种暗示似乎没有必要:通过IInvariant
禁止.TInv
M
function - Kotlin:混淆 lambda 和泛型
请在评论中查看错误消息:
关键点:
bookPrint()
并且authorPrint()
都需要一本空书/作者printIt()
需要采取其中任何一个功能。
所以,考虑“生产者扩展,消费者超级”我认为我的问题是我希望输入参数是协变的,当它被硬编码为逆变(“in”)时。
我有这个想法没有奏效: