C#支持返回类型协变,但为什么不支持参数类型逆变。
想象一下这个例子:
abstract class Animal
{
public abstract void PlayWith(Toy toy);
}
class PlayfulMonkey : Animal
{
public override void PlayWith(Object toy) // PlayfulMonkey can play with anything
{
// Monkey playing with its object...
}
}
Run Code Online (Sandbox Code Playgroud)
当您尝试执行此操作时,C# 编译器会向您抛出错误。但我觉得允许这样做是很有意义的。
abstract class A<T> {
List<T> Items { get; set; }
}
class B {}
class C : A<B> {}
class D : B {}
class E : A<D> {}
static class X {
public A<B> GetThing(bool f) {
return f ? new E() : new C();
}
}
Run Code Online (Sandbox Code Playgroud)
无法确定条件表达式的类型,因为"ConsoleApplication4.E"和"ConsoleApplication4.C"之间没有隐式转换
现在我得到了"为什么"(我认为),但我看不出如何编译.我想我必须创建一个定义某种方差的接口并从中继承,但我不确定.但无论如何,E()都应该继承C().
任何接受者?
TIA
请考虑以下代码:
ICondition searchCondition, scopeCondition...
List<ICondition> filtered = CollectionUtil.filter(
Arrays.asList(searchCondition, scopeCondition),
CollectionUtil.isNonNull);
Run Code Online (Sandbox Code Playgroud)
它无法编译:
"该
filter(Collection<T>, CollectionUtil.Predicate<T>)类型的方法CollectionUtil不适用于参数(List<ICondition>, CollectionUtil.Predicate<Object>)"
如果我定义一个ICondition特定的isNonNull()谓词,一切都很好,但这是愚蠢的,我不明白什么是错的或如何解决它.
这是我的实用功能:
public interface Predicate<T>
{
boolean apply(T type);
}
public static <T> List<T> filter(Collection<T> target, Predicate<T> predicate)
{
target = Collections.unmodifiableCollection(target);
List<T> result = new ArrayList<T>();
for (T element: target) {
if (predicate.apply(element)) {
result.add(element);
}
}
return result;
}
// This predicate works as expected.
public static CollectionUtil.Predicate<String> isStringNonBlank = new CollectionUtil.Predicate<String>() { …Run Code Online (Sandbox Code Playgroud) 我有以下代码:
class Header<TItem> where TItem : IItem { IEnumerable<TItem> Item { get; set; } }
class HeaderA : Header<ItemA> { public HeaderA(int a) {...} }
class HeaderB : Header<ItemB> { public HeaderB(int b) {...} }
interface IItem {...}
class ItemA : IItem { }
class ItemB : IItem { }
public static List<Header<IItem>> list = new List<Header<IItem>>
{
new HeaderA(1)
}
Run Code Online (Sandbox Code Playgroud)
最后的编译错误new HeaderA(1)是
Error 1 The best overloaded Add method
'System.Collections.Generic.List<NS.Header<NS.IItem>>.Add(NS.Header<NS.IItem>)'
for the collection initializer has some invalid …Run Code Online (Sandbox Code Playgroud) 在Scala课程的FP中,Martin提到,论证是"逆变",而返回类型是"协变".我不认为我完全理解这一点 - 有人可以帮助这个吗?
在Nomicon的有关子类型的部分中,它说函数变量类型可以使用逆方差。但是,我找不到任何很好的例子。我试图用一个函数指针编码一个结构,但是矛盾似乎不起作用。
这是什么代码示例?
方差(尤其是逆变)问题让我头撞墙一周了。由于这里的几个问题,我终于理解了这个理论,现在一旦我开始研究它,我就会遇到我不明白的错误。
我有一个简单的类层次结构:
抽象类 Fruit,Mango 扩展 Fruit,Orange 扩展 Fruit,BloodOrange 扩展 Orange
abstract class Fruit implements PlantEatable {
private boolean isRipe;
private boolean isEatable;
public boolean isRipe() {
return isRipe;
}
public void setRipe(boolean ripe) {
isRipe = ripe;
}
@Override
public boolean isEatable() {
return isEatable;
}
public void setEatable(boolean eatable) {
isEatable = eatable;
}
}
public class Mango extends Fruit {
}
public class Orange extends Fruit{
}
public class BloodOrange extends Orange{
}
Run Code Online (Sandbox Code Playgroud)
现在,Oracle 文档总体上对泛型非常了解,除了我觉得令人困惑的最重要的部分:https ://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html
如果我正在做 …
Smalltalk是否支持协方差和逆变?这些概念适用于这种语言吗?