实施与扩展:何时使用?有什么不同?


Answers:


734

extends用于扩展课程。

implements用于实现接口

接口和常规类之间的区别在于,在接口中不能实现任何已声明的方法。只有“实现”接口的类才能实现方法。接口的C ++等效项将是一个抽象类(不完全相同,但差不多)。

同样,java不支持类的多重继承。这可以通过使用多个接口来解决。

 public interface ExampleInterface {
    public void doAction();
    public String doThis(int number);
 }

 public class sub implements ExampleInterface {
     public void doAction() {
       //specify what must happen
     }

     public String doThis(int number) {
       //specfiy what must happen
     }
 }

现在延伸一堂课

 public class SuperClass {
    public int getNb() {
         //specify what must happen
        return 1;
     }

     public int getNb2() {
         //specify what must happen
        return 2;
     }
 }

 public class SubClass extends SuperClass {
      //you can override the implementation
      @Override
      public int getNb2() {
        return 3;
     }
 }

在这种情况下

  Subclass s = new SubClass();
  s.getNb(); //returns 1
  s.getNb2(); //returns 3

  SuperClass sup = new SuperClass();
  sup.getNb(); //returns 1
  sup.getNb2(); //returns 2

我建议您对面向对象编程中的动态绑定,多态性和一般继承性进行更多研究


46
接口可以包含的方法不只是方法声明:常量字段,注释,接口甚至类。
菲利普·里查特

它们是红宝石中的模块和mixins吗?
user2492854

@ user2492854有点,但是接口中不会有任何实现的方法。它实际上是对接口的描述,而不是实现。
罗布·格兰特

34
Java 8中的一项新功能允许default在接口中实现方法的行为,从而使这些方法的自定义实现成为可选项。因此,语句“您只能指定方法,而不能实现方法”仅对Java 7及以下版本完全正确。
ADTC

5
“扩展是为了扩展一个类”,有点令人困惑。正弦接口,也扩展接口。例如:public interface ListIterator<E> extends Iterator<E>
weiheng

77

我注意到您的个人资料中有一些C ++问题。如果您了解C ++ 的多重继承的概念(指的是从多个其他类继承特性的类),则Java不允许这样做,但它确实具有keyword interface,这有点像C ++中的纯虚拟类。正如很多人提到的,您可以创建extend一个类(并且只能从一个类扩展),还可以创建implement一个接口-但是您的类可以实现任意数量的接口。

即,这些关键字和控制其使用的规则描述了Java中多重继承的可能性(您只能有一个超类,但可以实现多个接口)。


51

通常工具用于实现一个接口延伸用于扩展的基类的行为或抽象类。

extend:派生类可以扩展基类。您可以重新定义已建立关系的行为。派生类“ ”基类类型

实现:您正在执行合同。实现接口“的类具有 ”功能。

在Java 8发行版中,interface可以在interface中具有默认方法,该方法在interface本身中提供实现。

有关何时使用它们的信息,请参考此问题:

接口vs抽象类(通用OO)

举例了解事物。

public class ExtendsAndImplementsDemo{
    public static void main(String args[]){

        Dog dog = new Dog("Tiger",16);
        Cat cat = new Cat("July",20);

        System.out.println("Dog:"+dog);
        System.out.println("Cat:"+cat);

        dog.remember();
        dog.protectOwner();
        Learn dl = dog;
        dl.learn();

        cat.remember();
        cat.protectOwner();

        Climb c = cat;
        c.climb();

        Man man = new Man("Ravindra",40);
        System.out.println(man);

        Climb cm = man;
        cm.climb();
        Think t = man;
        t.think();
        Learn l = man;
        l.learn();
        Apply a = man;
        a.apply();

    }
}

abstract class Animal{
    String name;
    int lifeExpentency;
    public Animal(String name,int lifeExpentency ){
        this.name = name;
        this.lifeExpentency=lifeExpentency;
    }
    public void remember(){
        System.out.println("Define your own remember");
    }
    public void protectOwner(){
        System.out.println("Define your own protectOwner");
    }

    public String toString(){
        return this.getClass().getSimpleName()+":"+name+":"+lifeExpentency;
    }
}
class Dog extends Animal implements Learn{

    public Dog(String name,int age){
        super(name,age);
    }
    public void remember(){
        System.out.println(this.getClass().getSimpleName()+" can remember for 5 minutes");
    }
    public void protectOwner(){
        System.out.println(this.getClass().getSimpleName()+ " will protect owner");
    }
    public void learn(){
        System.out.println(this.getClass().getSimpleName()+ " can learn:");
    }
}
class Cat extends Animal implements Climb {
    public Cat(String name,int age){
        super(name,age);
    }
    public void remember(){
        System.out.println(this.getClass().getSimpleName() + " can remember for 16 hours");
    }
    public void protectOwner(){
        System.out.println(this.getClass().getSimpleName()+ " won't protect owner");
    }
    public void climb(){
        System.out.println(this.getClass().getSimpleName()+ " can climb");
    }
}
interface Climb{
    public void climb();
}
interface Think {
    public void think();
}

interface Learn {
    public void learn();
}
interface Apply{
    public void apply();
}

class Man implements Think,Learn,Apply,Climb{
    String name;
    int age;

    public Man(String name,int age){
        this.name = name;
        this.age = age;
    }
    public void think(){
        System.out.println("I can think:"+this.getClass().getSimpleName());
    }
    public void learn(){
        System.out.println("I can learn:"+this.getClass().getSimpleName());
    }
    public void apply(){
        System.out.println("I can apply:"+this.getClass().getSimpleName());
    }
    public void climb(){
        System.out.println("I can climb:"+this.getClass().getSimpleName());
    }
    public String toString(){
        return "Man :"+name+":Age:"+age;
    }
}

输出:

Dog:Dog:Tiger:16
Cat:Cat:July:20
Dog can remember for 5 minutes
Dog will protect owner
Dog can learn:
Cat can remember for 16 hours
Cat won't protect owner
Cat can climb
Man :Ravindra:Age:40
I can climb:Man
I can think:Man
I can learn:Man
I can apply:Man

要了解的重点:

  1. 是动物,它们通过共享来扩展remember()和protectOwner()name,lifeExpentencyAnimal
  2. 猫可以爬(),而狗则不能。狗可以认为(),而猫则不能。这些特定功能已添加到该功能CatDog通过实施该功能。
  3. 人不是动物,但他可以 Think,Learn,Apply,Climb

通过查看这些示例,您可以了解

不相关的类可以通过接口具有功能,但是相关的类可以通过扩展基类来覆盖行为。


1
很好解释。它只是单击。谢谢一群!
Emir Memic '16

真的是这样吗?我一直认为“有”是指拥有某物并拥有它。您可以说猫具有“爬山”的能力,但我想说一下您的榜样。猫是“登山者”,人是“思想者,学习者,登山者”。由于人是“思想家”,他可以做思想家可以做的事情。使用某些协议时甚至更清楚-如果您有房子,有门,但没有实现pushHandle。它也是“ MaterialObject”,意味着它实现了服从重力的接口;没有“ GravityObeyingSkill”或类似的东西
MatthewRock

如果人是思想家,我将与扩展而不是实现建立关系。思想者可能具有某些状态和其他角色/功能,但是我将仅通过界面来实现思想能力。IS A是用于继承的标准术语。
拉文德拉·巴布

@Ravindrababu非常感谢您提供如此清晰的解释。
kanudo

1
很好的解释!
Dary


34

一个class只能“实现”一个interface。一个类仅“扩展” a class。同样,interface可以扩展另一个interface

A class只能互相延伸class。一个class可以实现多个interface

相反,如果您更想知道何时使用abstract classes和interfaces,请参考此线程:接口与抽象类(通用OO)


2
您还可以扩展接口。
马克·彼得斯

2
一个class只能实现一个interface。A class可以扩展其他几个类。我相信您已经倒退了。
pb2q

只是为了澄清pb2q的评论,答案已经被编辑/纠正。正确的陈述是:“一个类只能扩展一个其他类。一个类可以实现多个接口”。
wisbucky

29

界面是对对象可以执行的操作的描述...例如,当您打开电灯开关时,电灯会亮着,您不在乎如何做,只是它确实在做。在面向对象的程序设计中,接口是对象成为“ X”必须具有的所有功能的描述。同样,作为示例,任何“像灯一样动作”的东西都应具有turn_on()方法和turn_off()方法。接口的目的是允许计算机强制执行这些属性,并知道TYPE T的对象(无论接口是什么)必须具有称为X,Y,Z等的函数。

接口是一种编程结构/语法,它允许计算机在对象(类)上强制某些属性。例如,假设我们有一个汽车班,一个踏板车班和一个卡车班。这三个类中的每个类都应具有一个start_engine()操作。每个车辆的“引擎启动”方式由每个特定类别决定,但是它们必须具有start_engine操作的事实是该接口的领域。


4
很好的解释;应该得到更多的认可。
Arvindh Mani

22

如下图所示,一个类扩展了另一个类,一个接口扩展了另一个接口,但是一个类实现了一个接口。 在此处输入图片说明

欲了解更多详情


16

扩展:用于将父类的属性获取到基类中,并且可以包含已经定义的方法,这些方法可以在子类中重写。

Implements:通过在子类中定义接口来实现接口(仅具有函数签名的父类,而不具有函数的定义)。

有一个特殊条件:“如果我希望新接口成为现有接口的子接口怎么办?”。在上述条件下,子接口扩展了父接口。


15
  • A扩展B:

    A和B都是类或都是接口

  • A工具B

    A是一个类,B是一个接口

  • 在Java中,A是接口而B是类的其余情况是不合法的。


12

工具用于接口,扩展用于扩展类。

为了用更简单的术语使其更加清晰,界面就像声音-界面-模型,您需要对其进行应用,遵循以及构思。

Extend用于类,在这里,您可以通过添加更多功能来扩展已存在的内容。

一些注意事项:

一个接口可以扩展另一个接口。

当您需要在实现接口还是为特定场景扩展类之间进行选择时,请去实现接口。因为一个类可以实现多个接口,但只能扩展一个类。


7

当子类扩展类时,它允许子类继承(重用)并覆盖超类型中定义的代码。当类实现接口时,它允许从该类创建的对象用于任何需要该接口值的上下文中。

真正的收获是,当我们执行任何事情时,它仅意味着我们按原样使用这些方法。它们的值和返回类型没有变化的余地。

但是,当我们扩展任何内容时,它将成为您课程的扩展。您可以对其进行更改,使用,重复使用,并且它不一定需要返回与超类相同的值。


我正在阅读我在9月19日超过三年后写的答案。我发誓我不明白自己写的东西。我现在可以写一个更好的答案。奇怪的事情。
Nikhil Arora

7

仅当子类要使用已在SuperClass中声明的某些功能(方法或实例变量)时,或者如果我想略微修改SuperClass的功能(方法重写)时,才使用SubClass扩展SuperClass。但是说,例如,我有一个Animal类(SuperClass)和Dog类(SubClass),而我在Animal类中定义的方法很少。doEat(); ,doSleep(); ... 还有很多。

现在,我的Dog类可以简单地扩展Animal类,如果我希望我的狗使用在Animal类中声明的任何方法,则可以通过简单地创建Dog对象来调用这些方法。因此,通过这种方式,我可以保证我有一只狗可以进食和睡觉,并且可以做我想让它做的其他事情。

现在,想象一下,有一天,有位爱猫人士进入我们的工作空间,她试图扩展Animal类(猫也吃饭和睡觉)。她制作了一个Cat对象,并开始调用方法。

但是,例如,有人试图使Animal类成为对象。您可以说出猫如何入睡,可以说出狗如何进食,也可以说出大象如何饮水。但这对于创建Animal类的对象没有任何意义。因为它是模板,所以我们不需要任何一般的饮食方式。

因此,我宁愿创建一个抽象类,该类没有人可以实例化,但可以用作其他类的模板。

综上所述,接口不过是一个抽象类(纯抽象类),它不包含任何方法实现,而仅包含定义(模板)。因此,只要实现接口的人都知道他们拥有doEat()的模板;和doSleep(); 但是他们必须定义自己的doEat(); 和doSleep(); 方法根据自己的需要。

仅当您想重用SuperClass的某些部分时才扩展(但请记住,您始终可以根据需要覆盖SuperClass的方法),并在需要模板并实现自己定义模板时实现(根据您的需要)。

我将与您分享一段代码:您可以使用不同的输入集尝试一下,然后查看结果。

class AnimalClass {

public void doEat() {

    System.out.println("Animal Eating...");
}

public void sleep() {

    System.out.println("Animal Sleeping...");
}

}

public class Dog extends AnimalClass implements AnimalInterface, Herbi{

public static void main(String[] args) {

    AnimalInterface a = new Dog();
    Dog obj = new Dog();
    obj.doEat();
    a.eating();

    obj.eating();
    obj.herbiEating();
}

public void doEat() {
    System.out.println("Dog eating...");
}

@Override
public void eating() {

    System.out.println("Eating through an interface...");
    // TODO Auto-generated method stub

}

@Override
public void herbiEating() {

    System.out.println("Herbi eating through an interface...");
    // TODO Auto-generated method stub

}


}

定义的接口

public interface AnimalInterface {

public void eating();

}


interface Herbi {

public void herbiEating();

}

7

使用Java语言创建自己的新类时,将使用两个关键字。

区别: implements意味着您在类中使用Java接口的元素。 extends表示您正在创建要扩展的基类的子类。您只能在子类中扩展一个类,但可以实现任意数量的接口。

有关更多详细信息,请参考界面上的oracle文档页面。

这可以帮助阐明接口是什么,以及有关使用接口的约定。


7

用最简单的术语来说,extends用来从类中继承,而implements用来在您的类中应用接口

扩展

public class Bicycle {
    //properties and methods
}
public class MountainBike extends Bicycle {
    //new properties and methods
}

实现

public interface Relatable {
    //stuff you want to put
}
public class RectanglePlus implements Relatable {
    //your class code
}

如果您仍然有困惑,请阅读以下内容:https : //docs.oracle.com/javase/tutorial/java/IandI/subclasses.html https://docs.oracle.com/javase/tutorial/java/IandI/usinginterface.html


5

接口都是契约。它们提供应用程序其他部分所依赖的方法和属性。

当您对合同的实施细节不感兴趣时​​,可以定义一个接口。唯一要关心的是合同(接口)存在。

在这种情况下,您可以将其留给实现接口的类,以关心合同如何履行的细节。只有类可以实现接口。

当您要替换现有合同的详细信息时,将使用extends。通过这种方式,您可以用另一种方式替换一种履行合同的方式。类可以扩展其他类,而接口可以扩展其他接口。


3

Extends在子类/接口中需要父类/接口的属性时使用,在类中需要接口implements时使用。

例:

  1. 使用类扩展

    家长类{

    }

    班级儿童扩展家长{

    }

  2. 使用界面扩展

    父界面{

    }

    子级扩展父级{

    }

  3. 机具

接口A {

}

B类实施A {

}

扩展和工具的结合

interface A{

}

class B

{

}

class C implements A,extends B{

}

2

延伸

  • 一堂课只延伸一堂课
  • 接口扩展了一个或多个接口

贯彻

  • 类实现一个或多个接口
  • 接口“不能”实现任何东西

抽象类也像类一样,具有扩展和实现


0

这两个关键字与继承直接附加在一起,它是OOP的核心概念。当我们将某个类继承到另一个类时,我们可以使用扩展,但是当我们要继承某些类的接口时,我们就不能使用扩展,而应该使用工具,并且可以使用extends关键字从另一个接口继承接口。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.