Реалізація проти розширень: Коли користуватися? Яка різниця?


719

Будь ласка, поясніть легкою для розуміння мовою чи посиланням на якусь статтю.


9
Посилання Цей приклад легко зрозумів інтерфейс та абстрактний клас, тобто реалізує і розширюється в java.
Навчання користувача

Відповіді:


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
Інтерфейс може містити набагато більше, ніж декларації методів: Постійні поля, анотації, інтерфейси і навіть класи.
Філіп Рейхарт

вони щось на кшталт модулів та міксин у рубіні?
user2492854

@ user2492854 небагато, але реалізованих методів в інтерфейсі не буде. Це буквально опис інтерфейсу, а не реалізація.
Роб Грант

34
Нова функція в Java 8 дозволяє реалізувати defaultповедінку для методів в інтерфейсах, що робить користувацьку реалізацію цих методів необов'язковою. Тому твердження "ви можете вказувати лише методи, але не реалізовувати їх" є цілком правильним лише для Java 7 та нижче .
ADTC

5
"extends - це розширення класу", трохи заплутано. Sine інтерфейс і розширює інтерфейс теж . Наприклад:public interface ListIterator<E> extends Iterator<E>
weiheng

77

Зауважую, у вас у профілі є деякі питання C ++. Якщо ви розумієте поняття множинного успадкування від C ++ (маючи на увазі класи, які успадковують характеристики більш ніж одного іншого класу), Java не дозволяє цього, але у нього є ключове слово interface, яке схоже на чистий віртуальний клас у C ++. Як згадується багатьма людьми, ви extendклас (і ви можете продовжити лише з одного), і виimplement інтерфейс - але ваш клас може реалізувати стільки інтерфейсів, скільки вам подобається.

Тобто, ці ключові слова та правила, що регулюють їх використання, визначають можливості для багатонаступного спадкування на Java (у вас може бути лише один суперклас, але ви можете реалізувати декілька інтерфейсів).


51

Зазвичай знаряддя використовуються для реалізації інтерфейсу і розширює використовуватися для розширення базового класу поведінки або абстрактного класу.

extends : Похідний клас може поширювати базовий клас. Ви можете переосмислити поведінку встановленого відношення. Отриманий клас " - це " тип базового класу

реалізація : Ви реалізуєте контракт. Клас, що реалізує інтерфейс, має "можливість".

З випуском java 8 інтерфейс може мати типовий параметр методи в інтерфейсі, який забезпечує реалізацію в самому інтерфейсі.

Зверніться до цього питання, коли використовувати кожне з них:

Інтерфейс проти абстрактного класу (загальний 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,lifeExpentencyзAnimal
  2. Кіт може піднятися (), але Собака ні. Собака може подумати (), але Кіт - ні . Ці конкретні можливості додаються Catта Dogреалізуються в цій можливості.
  3. Людина - не тварина, але вміє Think,Learn,Apply,Climb

Пройшовши ці приклади, ви можете це зрозуміти

Неспоріднені класи можуть мати можливості через інтерфейс, але пов'язані класи перекривають поведінку через розширення базових класів.


1
Дуже добре пояснено. Це просто натиснуло. Дякую купу!
Емір Меміч

Це справді так? Я завжди думав, що "має" відноситься до того, щоб мати щось, володіти ним. Можна сказати, що кішка "має" здатність до сходження, але я б сказав переформулювати ваш приклад. Кіт "- це" Альпініст ", людина" - "мислитель, вчитель, альпініст". Оскільки людина "є" мислителем, він може робити те, що може зробити мислитель. Це ще зрозуміліше, працюючи з деякими протоколами - якщо ви є будинок, у нього є двері, але він не реалізує pushHandle. Він також "є" MaterialObject, тобто він реалізує інтерфейс для підкорення гравітації; у нього немає "GravityObeyingSkill" або чогось подібного.
MatthewRock

Якщо Людина - мислитель, я буду встановлювати стосунки з розширеннями, а не знаряддями. Мислитель може мати деякі стани та інші ролі / функції, але я буду реалізовувати можливості мислення лише за допомогою інтерфейсу. IS A - це стандартний термін, який використовується для успадкування.
Равіндра бабу

@Ravindrababu Дякую за таке чітке пояснення.
канудо

1
чудово пояснив!
Дари

43

extendsпризначений для, коли ви успадковуєте базовий клас (тобто розширюєте його функціональність).

implementsпризначений для впровадження інтерфейсу .

Тут є гарне місце для початку: Інтерфейси та Спадщина .


24
І розширення - це також коли ви розширюєте інтерфейс :-).
Марк Петерс

34

А classможе лише "реалізувати" ан interface. Клас лише "розширює" a class. Так само interfaceможе бути розповсюджений інший interface.

А classможуть поширюватися лише один на одного class. A classможе реалізувати кілька interfaces.

Якщо замість цього вам більше цікаво знати, коли використовувати abstract classes та interfaces, зверніться до цієї теми: Інтерфейс проти абстрактного класу (загальний OO)


2
Ви також можете розширити інтерфейс.
Марк Петерс

2
А classможе реалізувати лише одне interface. А classможна поширити на кілька інших класів. Я вірю, що ти це зрозумів назад.
pb2q

Просто для уточнення коментаря pb2q відповідь уже відредаговано / виправлено. "Клас може поширювати лише один інший клас. Клас може реалізувати кілька інтерфейсів" - це правильне твердження.
wisbucky

29

Інтерфейс - це опис дій, які може виконувати об’єкт ... наприклад, коли ви перемикаєте перемикач світла, світло вимикається, вам не байдуже, як це відбувається. В об'єктно-орієнтованому програмуванні інтерфейс - це опис усіх функцій, які повинен мати об'єкт, щоб бути "X". Знову ж, як приклад, все, що "ACTS LIKE" light, має мати метод turn_on () та метод turn_off (). Мета інтерфейсів - дозволити комп'ютеру застосовувати ці властивості та знати, що об’єкт TYPE T (незалежно від інтерфейсу) повинен мати функції, що називаються X, Y, Z тощо.

Інтерфейс - це структура / синтаксис програмування, що дозволяє комп'ютеру застосовувати певні властивості об'єкта (класу). Наприклад, скажімо, у нас є клас автомобілів, скутер і клас вантажівки. Кожен із цих трьох класів повинен мати дію start_engine (). Як "запускається двигун" для кожного транспортного засобу, залишається кожному конкретному класу, але факт, що вони повинні мати дію start_engine, - це область інтерфейсу .


4
Чудове пояснення; заслуговує на більше визнання.
Арвінд Мані

22

Як показано на малюнку, наведеному нижче, клас розширює інший клас, інтерфейс розширює інший інтерфейс, але клас реалізує інтерфейс. введіть тут опис зображення

Для отримання більш докладної інформації


16

Розширення : використовується для отримання атрибутів батьківського класу до базового класу і може містити вже визначені методи, які можна перекрити в дочірньому класі.

Програми : використовується для реалізації інтерфейсу (батьківського класу з підписами функцій, але не їх визначеннями) шляхом визначення його в дочірньому класі.

Є одна особлива умова: "Що робити, якщо я хочу, щоб новий інтерфейс був дочірнім наявним інтерфейсом?". У вищевказаній умові дочірній інтерфейс розширює батьківський інтерфейс.


15
  • А подовжує B:

    А і В - обидва класи або обидва інтерфейси

  • А знаряддя Б

    A - клас, а B - інтерфейс

  • Інший випадок, коли A - інтерфейс, а B - клас, не є законним для Java.


12

Implements використовується для інтерфейсів, а extends використовується для розширення класу.

Щоб зробити його більш зрозумілим у більш легких термінах, інтерфейс схожий на його звучання - інтерфейс - модель, яку потрібно застосувати, дотримуватися разом із своїми ідеями до неї.

Extend використовується для класів, тут ви розширюєте те, що вже існує, додаючи до нього більше функціональності.

Ще кілька приміток:

інтерфейс може розширити інший інтерфейс.

І коли вам потрібно вибрати між реалізацією інтерфейсу або розширенням класу для певного сценарію, перейдіть до реалізації інтерфейсу. Тому що клас може реалізовувати декілька інтерфейсів, але поширювати лише один клас.


7

Коли підклас розширює клас, він дозволяє підкласу успадковувати (повторно використовувати) та переосмислювати код, визначений у супертипі. Коли клас реалізує інтерфейс, він дозволяє використовувати об’єкт, створений з класу, в будь-якому контексті, який очікує значення інтерфейсу.

Справжня уловка полягає в тому, що, хоча ми впроваджуємо будь-що, це просто означає, що ми використовуємо такі методи, як є. Немає можливості змінювати їх значення та типи повернення.

Але коли ми щось продовжуємо, то це стає розширенням вашого класу. Ви можете його змінити, використовувати, повторно використовувати, і не обов’язково повертати ті самі значення, що і в суперкласі.


Я читаю цю відповідь, написану мною через більше 3 років, 19 вересня. Клянусь, я не в змозі зрозуміти, яке лайно я написав. Я міг би зараз написати набагато кращу відповідь. Дивна річ.
Nikhil Arora

7

Ми використовуємо SubClass розширює SuperClass лише тоді, коли підклас хоче використовувати деяку функціональність (методи або змінні екземпляра), яка вже оголошена в SuperClass , або якщо я хочу трохи змінити функціональність SuperClass (Метод переопределення). Але скажіть, наприклад, у мене є клас Animal ( SuperClass ) і Dog ( SubClass ), і є кілька методів, які я визначив у класі Animal, наприклад. doEat (); , doSleep (); ... та багато іншого.

Тепер мій клас Собака може просто розширити клас Animal, якщо я хочу, щоб моя собака використовувала будь-який із методів, оголошених у класі Animal, я можу викликати ці методи, просто створивши об'єкт Dog. Таким чином, я можу гарантувати, що у мене є собака, яка може їсти і спати, і робити все, що я хочу, щоб собака займалася.

А тепер, уявіть, одного дня любитель кішок заходить у наш робочий простір, і вона намагається розширити клас Animal (коти також їдять і сплять). Вона робить об'єкт Cat і починає викликати методи.

Але, скажімо, хтось намагається зробити об’єкт класу Тварини. Ви можете сказати, як кішка спить, ви можете сказати, як собака їсть, ви можете сказати, як п'є слон. Але це не має сенсу робити об’єкт класу 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 використовується для успадкування класу, а інструменти застосовуються для застосування інтерфейсу у вашому класі

розширюється :

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

Класи та інтерфейси - це контракти . Вони надають методи та властивості, на які покладаються інші частини програми.

Інтерфейс ви визначаєте, коли вас не цікавлять деталі реалізації цього договору. Єдине, про що слід подбати - це те, що контракт (інтерфейс) існує.

У цьому випадку ви залишаєте це до класу, який реалізує інтерфейс, щоб дбати про деталі, як виконується контракт. Тільки класи можуть реалізовувати інтерфейси.

продовження використовується, коли ви хочете замінити деталі існуючого контракту. Таким чином ви замінюєте один спосіб виконання договору іншим способом. Класи можуть розширювати інші класи, а інтерфейси - інші інтерфейси.


3

Extendsвикористовується, коли потрібно атрибути батьківського класу / інтерфейсу у вашому дочірньому класі / інтерфейсі та implementsвикористовується, коли потрібно атрибути інтерфейсу у вашому класі.

Приклад:

  1. Розширення за допомогою класу

    батьківський клас {

    }

    клас Дитина продовжує батьківський {

    }

  2. Розширюється за допомогою інтерфейсу

    батьківський інтерфейс {

    }

    інтерфейс Child розширює Батько {

    }

  3. Здійснення

інтерфейс A {

}

клас B реалізує A {

}

Поєднання нарощувань та інструментів

interface A{

}

class B

{

}

class C implements A,extends B{

}

2

розширюється

  • клас поширюється лише на один клас
  • інтерфейс розширює один або кілька інтерфейсів

знаряддя

  • клас реалізує один або кілька інтерфейсів
  • інтерфейси "не можуть" нічого не реалізують

абстрактні класи також діють як клас, з розширеннями та інструментами


0

Ці два ключові слова безпосередньо приєднані до Inheritance - це основна концепція OOP. Коли ми успадковуємо деякий клас до іншого класу, ми можемо використовувати розширення, але коли ми збираємось успадкувати деякі інтерфейси до нашого класу, ми не можемо використовувати розширення, ми повинні використовувати інвентар, і ми можемо використовувати ключове слово розширення для успадкування інтерфейсу від іншого інтерфейсу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.