如果在 C# 中可以进行以下操作,我只是在徘徊。
假设我有一个类似 List 的界面来强制执行操作reverse
。IE:
public interface ReversableList<T> {
// Return a copy of this list but reversed
ReversableList<T> Reverse();
// We still need to return the contained type sometimes
T Get(int index)
}
但是,现在当我去实现该接口时:
public class ListImplementation<T> : ReversableList<T>
ReversableList<T> Reverse();
}
我仍然被迫使用界面ReversableList
。所以即使用户直接实例化my ,调用方法时ListImplementation
还是要强制处理:ReversableList
Reverse
var concreteList = new ListImplementation<String>();
ReversableList<T> reversed = concreteList.Reverse();
而我想到Reverse()
的是ListImplementation
will 是 another ListImplementation
,就像这样:
var concreteList = new ListImplementation<String>();
ListImplementation<String> reversed = concreteList.Reverse();
同时仍然实现了足够通用的接口。
如果这令人困惑,请告诉我,我将澄清/添加任何必要的细节或更正。谢谢!
兴趣来源
以下是为什么这对我来说很有趣的解释。
我通过它继承的所有接口(特征)跟踪了 scala 集合中调用的函数(这是一个具体reversed
类型)。List
我的发现非常好奇。
原始reverse
方法是在GenSeqLike
trait上抽象定义的。
trait GenSeqLike[+A, +Repr] ...
def reverse: Repr // <--- NO BODY, means abstract
然后,它在扩展trait的trait SeqLike中具体定义:GenSeqLike
trait SeqLike[+A, +Repr] extends GenSeqLike[A, Repr]
def reverse: Repr
//iterates through this seqence
// and reverses
for (x <- this)
//...etc
然后,有趣的是接下来的两个特征:
trait Seq[+A] extends SeqLike[A, Seq[A]] //<-- NOTE here is the type for "Repr"
//no mention of reverse
trait LinearSeq[+A] extends Seq[A] with SeqLike[A, Seq[A]] //<-- NOTE type again
// no mention of reverse
两者都获得了该reverse
功能的“免费”版本,但它们都根据各自的“接口”(特征)工作。所以reverse
onSeq
返回一个Seq
.
最后,List
具体类实现了LinearSeq
特征并重新定义了reverse
方法(我假设是为了提高效率)。
sealed abstract class List[+A] extends LinearSeq[A]
with LinearSeqOptimized[A, List[A]]
override def reverse: List[A] = {
//faster impl without foreach iteration
...
}
其中LinearSeqOptimized
只是另一个一直到 的特征“链” SeqLike[A, Repr]
。
所以你可以看到,一个通用的“接口”是如何被用来指定一些“行为”的,一个中间的“接口”是如何提供某种“默认的”实现的,以及所有的子“接口”和子类型是如何获得好处的该实现的同时将返回类型保留为它们的“自己的”类型。呸。令人困惑,我知道!