在我学习Haskell的过程中,我注意到它的类型类,它应该是一个源自Haskell的伟大发明.
但是,在类型类的维基百科页面中:
程序员通过指定一组函数或常量名称以及它们各自的类型来定义类型类,这些类型必须存在于属于该类的每个类型.
这似乎与Java的界面非常接近(引用维基百科的界面(Java)页面):
Java编程语言中的接口是一种抽象类型,用于指定类必须实现的接口(在术语的一般意义上).
这两个看起来很相似:类型类限制了类型的行为,而接口限制了类的行为.
我想知道Haskell中的类类和Java中的接口之间有什么区别和相似之处,或者它们可能根本不同?
编辑:我注意到即使haskell.org也承认它们是相似的.如果它们如此相似(或者它们是什么?),那么为什么类型类会受到这样的炒作?
更多编辑:哇,这么多很棒的答案!我想我必须让社区决定哪个是最好的.然而,在阅读答案时,所有人似乎都只是说"在界面无法或不得不应对泛型时,类节目可以做很多事情".我不禁想知道,有什么接口可以做而类型不能吗?此外,我注意到维基百科声称类型类最初是在1989年的论文中发明的*"如何使ad-hoc多态性不那么特别",而Haskell仍处于摇篮之中,而Java项目始于1991年并于1995年首次发布那么也许代码类似于接口,而另一种方式,接口受类型类的影响?是否有任何文件/文件支持或反驳?感谢所有答案,他们都非常有启发性!
感谢所有的投入!
public interface IDic
{
int Id { get; set; }
string Name { get; set; }
}
public class Client : IDic
{
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能投List<Client>
来List<IDic>
?
您可能知道,C#中的数组实现IList<T>
了其他接口.但不知何故,他们这样做没有公开实现Count属性IList<T>
!数组只有一个Length属性.
这是一个明显的例子,C#/ .NET打破了自己关于接口实现的规则,还是我错过了什么?
我只是想了解为什么在接口定义的所有域都默认static
和final
.保持字段的想法static
对我来说是有道理的,因为你不能拥有接口的对象,但为什么它们final
(隐含地)?
任何人知道为什么Java的设计者在接口使得场去static
和final
?
我们可以像在java中那样公开Ruby中的接口,并强制执行Ruby模块或类来实现接口定义的方法.
一种方法是使用继承和method_missing来实现相同的目标,但还有其他更合适的方法吗?
可能重复:
如何在C++中声明接口?
这是关于C++的一般问题.如你所知,目前还没有明确的区分之间interface
以及abstract class
在C++与Java和C#.什么时候更喜欢用C++ interface
代替abstract class
?你能举一些例子吗?
在初始化类之前,必须初始化其直接超类,但不会初始化类实现的接口.同样,在初始化接口之前,不会初始化接口的超接口.
为了我自己的好奇心,我尝试了它,正如预期的那样,界面InterfaceType
没有被初始化.
public class Example {
public static void main(String[] args) throws Exception {
InterfaceType foo = new InterfaceTypeImpl();
foo.method();
}
}
class InterfaceTypeImpl implements InterfaceType {
@Override
public void method() {
System.out.println("implemented method");
}
}
class ClassInitializer {
static {
System.out.println("static initializer");
}
}
interface InterfaceType {
public static final ClassInitializer init = new ClassInitializer();
public void method();
}
Run Code Online (Sandbox Code Playgroud)
这个程序打印
implemented method
Run Code Online (Sandbox Code Playgroud)
但是,如果接口声明了default
方法,则会发生初始化.考虑InterfaceType
给出的接口为
interface InterfaceType {
public …
Run Code Online (Sandbox Code Playgroud) 这里提出了一些问题,为什么你不能在接口中定义静态方法,但它们都没有解决基本的不一致性:为什么你可以在接口中定义静态字段和静态内部类型,而不是静态方法?
静态内部类型可能不是一个公平的比较,因为这只是产生一个新类的语法糖,但为什么是字段而不是方法?
接口中的静态方法的一个参数是它破坏了JVM使用的虚拟表解析策略,但是不应该同样适用于静态字段,即编译器可以内联它吗?
一致性是我想要的,Java应该支持接口中没有任何形式的静态,或者它应该是一致的并允许它们.
在Collection Interface中,我找到了一个removeIf()
包含其实现的名为的方法.
default boolean removeIf(Predicate<? super E> filter) {
Objects.requireNonNull(filter);
boolean removed = false;
final Iterator<E> each = iterator();
while (each.hasNext()) {
if (filter.test(each.next())) {
each.remove();
removed = true;
}
}
return removed;
}
Run Code Online (Sandbox Code Playgroud)
我想知道是否有任何方法可以在接口中定义方法体?
什么是default
关键字,它是如何工作的?
我很熟悉在Go中,接口定义功能而不是数据.您将一组方法放入接口,但是您无法指定实现该接口的任何字段.
例如:
// Interface
type Giver interface {
Give() int64
}
// One implementation
type FiveGiver struct {}
func (fg *FiveGiver) Give() int64 {
return 5
}
// Another implementation
type VarGiver struct {
number int64
}
func (vg *VarGiver) Give() int64 {
return vg.number
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以使用接口及其实现:
// A function that uses the interface
func GetSomething(aGiver Giver) {
fmt.Println("The Giver gives: ", aGiver.Give())
}
// Bring it all together
func main() {
fg := &FiveGiver{}
vg := &VarGiver{3}
GetSomething(fg)
GetSomething(vg) …
Run Code Online (Sandbox Code Playgroud)