Rust特性是否与Java接口相同 [英] Is Rust trait the same as Java interface

查看:17
本文介绍了Rust特性是否与Java接口相同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我看来,Rust的trait与Java的interface是一样的--一组需要在对象上实现的函数。

将其命名为trait而不是interface是出于技术原因还是出于某种偏好?

推荐答案

RUST特征和Java接口都解决了这样一个问题,即有多个可能的实现遵循某种约定/协议/接口来与值/对象交互,而不像Java超类那样约束实现细节。它们可以在许多相同的情况下使用。然而,它们在许多细节上是不同的,大多意味着锈病性状更强大:

  • Java接口要求实现对象具有具有特定名称的方法。铁锈特征有一个完全不同的名称空间。在Java中,两个接口可能不可能同时实现:

    interface Foo {
      void someMethod();
    }
    interface Bar {
      int someMethod();
    }
    class TwoInterfaces implements Foo, Bar {
      public int someMethod();  // The return type must be void and also must be int
    }
    

    在Rust中,特征的每个实现都位于它自己的impl块中,它们被认为是不同的。这意味着为类型实现特征不能与不同的特征冲突(除了在作用域中同时具有两个特征的调用位置,这必须通过使用函数语法而不是方法语法来消除歧义)。

  • Java特征可以有泛型(类型参数),SomeInterface<T>,但一个对象只能实现一次接口。

    class TwoGenerics implements Foo<Integer>, Foo<String> {
      public void someMethod(??? value) {}  // Can't implement, must be one method
    }
    interface Foo<T> {
      void someMethod(T value);
    }
    

    在Rust中,一个特征可以实现许多类型,这些基本上就像不同的特征一样:

    struct TwoGenerics;
    
    trait Foo<T> {
        fn some_method(&self, input: T);
    }
    
    impl Foo<i32> for TwoGenerics {
        fn some_method(&self, input: i32) {}
    }
    impl Foo<String> for TwoGenerics {
        fn some_method(&self, input: String) {}
    }
    

    若要获得类似Java的行为,即要求任何实现类型都有一个特定类型,您可以定义关联类型而不是泛型:

    struct Thing;
    
    trait Foo {
        type Input;
        fn some_method(&self, input: Self::Input);
    }
    
    impl Foo for Thing {
        type Input = i32;
        fn some_method(&self, input: i32) {}
    }
    
  • 在Rust中,如果您定义了特征,则可以为未定义的类型实现特征。因此,您可以在机箱中定义一个特征,然后为标准库(或您所依赖的其他库)中的相关类型实现它,例如用于序列化、随机生成、遍历等。在Java中,需要运行时类型检查等变通方法才能获得类似的结果。

  • 在Rust中,特征可能具有适用于满足某些条件(界限)的所有类型的泛型实现,或者仅当其参数合适时才应用于特定泛型类型的实现。例如,在标准库中,有(大约)

    impl<T> Clone for Vec<T> where T: Clone {...}
    
    因此Vec是可克隆的,当且仅当其内容是可克隆的。在Java中,类不能有条件地实现接口,这对于任何递归属性都是有问题的:例如,list instanceof Serializable可能为真,而列表将无法序列化,因为它的一个或多个元素不可序列化。

  • Rust特征可能具有关联的常量、类型和非方法函数(类似于Javastatic方法),所有这些对于每个实现类型都可能不同。当Java接口有static成员时,它们对整个接口只有一个实现。

    例如,Rust中的Default特征允许通过调用Default::default()T::default()来构造任何实现类型的新实例。在Java中,您需要创建一个单独的"工厂"接口来完成此操作。

  • 锈蚀特征可以具有接受也属于实现类型的多个输入(或产生输出)的函数。Java接口不能引用实现类型;它们只能添加不需要相同的类型参数。(另一方面,Java有子类化(子类化),而Rust没有子类化,因此当您有不同具体类型但相同超类型的实例集合时,情况必然会更加复杂。)

可能还有更多细节可以提及,但我认为这些内容涵盖了您可以或必须以不同方式使用它们的许多方式,即使它们用于相同的任务。


关于名称"特征"与"接口",这是因为现有的concept of traits in computer science被认为具有几个特定的属性,主要是在实现和使用特征时没有继承覆盖。这与我上面提到的"独立命名空间"密切相关。

这篇关于Rust特性是否与Java接口相同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆