Implements vs extends: Khi nào nên sử dụng? Có gì khác biệt?


Câu trả lời:


735

extendslà để mở rộng một lớp học.

implementslà để thực hiện một giao diện

Sự khác biệt giữa một giao diện và một lớp thông thường là trong một giao diện, bạn không thể thực hiện bất kỳ phương thức khai báo nào. Chỉ có lớp "thực hiện" giao diện có thể thực hiện các phương thức. Tương đương C ++ của một giao diện sẽ là một lớp trừu tượng (không hoàn toàn giống nhau nhưng khá nhiều).

Ngoài ra java không hỗ trợ nhiều kế thừa cho các lớp. Điều này được giải quyết bằng cách sử dụng nhiều giao diện.

 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
     }
 }

bây giờ mở rộng một lớp học

 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;
     }
 }

trong trường hợp này

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

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

Tôi đề nghị bạn thực hiện một số nghiên cứu thêm về liên kết động, đa hình và kế thừa chung trong lập trình hướng đối tượng


46
Một giao diện có thể chứa nhiều hơn cách khai báo phương thức: Các trường không đổi, chú thích, giao diện và thậm chí các lớp.
Philipp Reichart

chúng có phải là một cái gì đó giống như các mô-đun và mixin trong ruby?
user2492854

@ user2492854 một chút, nhưng sẽ không có bất kỳ phương thức được thực hiện nào trong một giao diện. Đó thực sự là một mô tả về một giao diện, không phải là một triển khai.
Rob Grant

34
Một tính năng mới trong Java 8 cho phép thực hiện defaulthành vi cho các phương thức trong các giao diện, làm cho việc triển khai tùy chỉnh các phương thức đó trở thành tùy chọn. Do đó, câu lệnh "bạn chỉ có thể chỉ định các phương thức, nhưng không triển khai chúng" chỉ hoàn toàn chính xác cho Java 7 trở xuống .
ADTC

5
"Mở rộng là để mở rộng một lớp", hơi khó hiểu. Sine một giao diện và mở rộng một giao diện quá . Ví dụ:public interface ListIterator<E> extends Iterator<E>
weiheng

78

Tôi nhận thấy bạn có một số câu hỏi C ++ trong hồ sơ của bạn. Nếu bạn hiểu khái niệm đa thừa kế từ C ++ (đề cập đến các lớp kế thừa các đặc điểm từ nhiều hơn một lớp khác), thì Java không cho phép điều này, nhưng nó có từ khóa interface, giống như một lớp ảo thuần trong C ++. Như nhiều người đã đề cập, bạn extendlà một lớp (và bạn chỉ có thể mở rộng từ một) và bạn có implementmột giao diện - nhưng lớp của bạn có thể thực hiện bao nhiêu giao diện tùy thích.

Tức là, các từ khóa này và các quy tắc điều chỉnh việc sử dụng chúng mô tả các khả năng đa kế thừa trong Java (bạn chỉ có thể có một siêu lớp, nhưng bạn có thể triển khai nhiều giao diện).


51

Nói chung dụng cụ được sử dụng để thực hiện một giao diệnmở rộng sử dụng cho phần mở rộng về hành vi lớp cơ sở hoặc trừu tượng lớp.

mở rộng : Một lớp dẫn xuất có thể mở rộng một lớp cơ sở. Bạn có thể xác định lại hành vi của một mối quan hệ được thiết lập. Lớp phái sinh " là một " loại lớp cơ sở

thực hiện : Bạn đang thực hiện một hợp đồng. Lớp thực hiện giao diện " " khả năng.

Với phiên bản java 8, giao diện có thể có các phương thức mặc định trong giao diện, cung cấp việc thực hiện trong chính giao diện.

Tham khảo câu hỏi này để biết khi nào nên sử dụng từng câu hỏi:

Giao diện so với lớp trừu tượng (chung OO)

Ví dụ để hiểu sự việc.

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;
    }
}

đầu ra:

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

Những điểm quan trọng cần hiểu:

  1. ChóMèo là động vật và chúng mở rộng remember() và protectOwner() bằng cách chia sẻ name,lifeExpentencytừAnimal
  2. Mèo có thể leo () nhưng Chó thì không. Chó có thể nghĩ () nhưng Cat thì không . Những khả năng cụ thể này được thêm vào CatDogbằng cách thực hiện khả năng đó.
  3. Con người không phải là động vật nhưng anh ta có thể Think,Learn,Apply,Climb

Bằng cách đi qua những ví dụ này, bạn có thể hiểu rằng

Các lớp không liên quan có thể có các khả năng thông qua giao diện nhưng các lớp liên quan sẽ ghi đè hành vi thông qua việc mở rộng các lớp cơ sở.


1
Giải thích rất tốt. Nó chỉ cần nhấp. Cảm ơn nhiều!
Dubai Memic

Có thật vậy không? Tôi luôn nghĩ "có một" đề cập đến việc có một cái gì đó, sở hữu nó. Bạn có thể nói rằng con mèo "có" khả năng leo trèo, nhưng tôi sẽ nói điều chỉnh lại ví dụ của bạn. Cat "là một" nhà leo núi ", người đàn ông" là một "" người suy nghĩ, người học, người leo núi ". Vì con người" là một "nhà tư tưởng, anh ta có thể làm những gì một nhà tư tưởng có thể làm. Thậm chí còn rõ ràng hơn khi làm việc với một số giao thức - nếu bạn có một ngôi nhà, nó có một cánh cửa, nhưng nó không thực hiện việc đẩy. Nó cũng "là một" MaterialObject, có nghĩa là nó thực hiện giao diện để tuân theo trọng lực, nó không có "GravityObeyingSkill" hoặc một cái gì đó tương tự.
MatthewRock

Nếu con người là một nhà tư tưởng, tôi sẽ thiết lập mối quan hệ với việc mở rộng và không thực hiện. Thinker có thể có một số trạng thái và vai trò / tính năng khác nhưng tôi sẽ thực hiện khả năng tư duy chỉ với giao diện. IS A là thuật ngữ tiêu chuẩn được sử dụng để thừa kế.
Ravindra babu

@Ravindrababu Rất cám ơn cho lời giải thích rõ ràng như vậy.
kanudo

1
giải thích tuyệt vời!
Dary

43

extendslà khi bạn kế thừa từ một lớp cơ sở (nghĩa là mở rộng chức năng của nó).

implementslà khi bạn đang thực hiện một giao diện .

Đây là một nơi tốt để bắt đầu: Giao diện và Kế thừa .


24
Và mở rộng cũng là khi bạn mở rộng giao diện :-).
Mark Peters

34

A classchỉ có thể "thực hiện" một interface. Một lớp chỉ "kéo dài" a class. Tương tự như vậy, một interfacecó thể mở rộng khác interface.

A classchỉ có thể mở rộng khác class. A classcó thể thực hiện một vài interfaces.

Nếu thay vào đó, bạn quan tâm hơn đến việc biết khi nào nên sử dụng abstract classes và interfaces, hãy tham khảo chủ đề này: Giao diện so với Lớp trừu tượng (chung OO)


2
Bạn cũng có thể mở rộng một giao diện.
Mark Peters

2
A classchỉ có thể thực hiện một interface. A classcó thể mở rộng một số lớp khác. Tôi tin rằng bạn đã nhận được điều này ngược.
pb2q

Chỉ cần làm rõ nhận xét bằng pb2q, câu trả lời đã được chỉnh sửa / sửa chữa. "Một lớp chỉ có thể mở rộng một lớp khác. Một lớp có thể thực hiện một số giao diện" là tuyên bố chính xác.
wvducky

29

Giao diện là một mô tả về các hành động mà một đối tượng có thể làm ... ví dụ: khi bạn bật công tắc đèn, đèn sẽ sáng, bạn không quan tâm làm thế nào, chỉ là nó làm như vậy. Trong Lập trình hướng đối tượng, Giao diện là một mô tả về tất cả các chức năng mà một đối tượng phải có để là "X". Một lần nữa, như một ví dụ, bất cứ điều gì "ACTS THÍCH" một ánh sáng, nên có một phương thức Turn_on () và phương thức Turn_off (). Mục đích của giao diện là cho phép máy tính thực thi các thuộc tính này và để biết rằng một đối tượng của TYPE T (dù giao diện là gì) phải có các chức năng gọi là X, Y, Z, v.v.

Giao diện là một cấu trúc / cú pháp lập trình cho phép máy tính thực thi các thuộc tính nhất định trên một đối tượng (lớp). Ví dụ: giả sử chúng ta có một lớp xe hơi và một lớp xe tay ga và một lớp xe tải. Mỗi trong ba lớp này nên có một hành động start_engine (). Làm thế nào "động cơ được khởi động" cho mỗi chiếc xe được để lại cho mỗi lớp cụ thể, nhưng thực tế là chúng phải có hành động start_engine là miền của giao diện .


4
Giải thích tuyệt vời; xứng đáng được công nhận hơn.
Arvindh Mani

22

Như thể hiện trong hình dưới đây, một lớp mở rộng một lớp khác, một giao diện mở rộng một giao diện khác nhưng một lớp thực hiện một giao diện. nhập mô tả hình ảnh ở đây

Để biết thêm chi tiết


16

Mở rộng : Điều này được sử dụng để đưa các thuộc tính của lớp cha vào lớp cơ sở và có thể chứa các phương thức đã được xác định có thể bị ghi đè trong lớp con.

Implements : Điều này được sử dụng để thực hiện một giao diện (lớp cha chỉ có chữ ký hàm chứ không phải định nghĩa của chúng) bằng cách định nghĩa nó trong lớp con.

Có một điều kiện đặc biệt: "Điều gì sẽ xảy ra nếu tôi muốn Giao diện mới là con của giao diện hiện tại?". Trong điều kiện trên, giao diện con mở rộng giao diện cha.


15
  • A kéo dài B:

    A và B là cả hai lớp hoặc cả hai giao diện

  • A thực hiện B

    A là một lớp và B là một giao diện

  • Trường hợp còn lại trong đó A là một giao diện và B là một lớp không hợp pháp trong Java.


12

Implements được sử dụng cho Giao diện và phần mở rộng được sử dụng để mở rộng một lớp.

Để làm cho nó rõ ràng hơn bằng các thuật ngữ dễ dàng hơn, một giao diện giống như âm thanh - một giao diện - một mô hình, mà bạn cần phải áp dụng, làm theo, cùng với ý tưởng của bạn với nó.

Extend được sử dụng cho các lớp, ở đây, bạn đang mở rộng một cái gì đó đã tồn tại bằng cách thêm nhiều chức năng hơn cho nó.

Một vài lưu ý nữa:

một giao diện có thể mở rộng giao diện khác.

Và khi bạn cần chọn giữa việc thực hiện một giao diện hoặc mở rộng một lớp cho một kịch bản cụ thể, hãy tiến hành thực hiện một giao diện. Bởi vì một lớp có thể thực hiện nhiều giao diện nhưng chỉ mở rộng một lớp.


7

Khi một lớp con mở rộng một lớp, nó cho phép lớp con kế thừa (tái sử dụng) và ghi đè mã được định nghĩa trong siêu kiểu. Khi một lớp thực hiện một giao diện, nó cho phép một đối tượng được tạo từ lớp được sử dụng trong bất kỳ bối cảnh nào mong đợi một giá trị của giao diện.

Điều thực sự ở đây là trong khi chúng ta đang thực hiện bất cứ điều gì, điều đó chỉ có nghĩa là chúng ta đang sử dụng các phương thức đó. Không có phạm vi để thay đổi giá trị và kiểu trả về của chúng.

Nhưng khi chúng tôi mở rộng bất cứ điều gì thì nó sẽ trở thành một phần mở rộng của lớp bạn. Bạn có thể thay đổi nó, sử dụng nó, sử dụng lại sử dụng nó và không nhất thiết phải trả về các giá trị giống như trong siêu lớp.


Tôi đang đọc câu trả lời này được viết bởi tôi sau hơn 3 năm nay vào ngày 19 tháng 9. Tôi thề tôi không thể hiểu những gì tôi đã viết. Tôi có thể viết một câu trả lời tốt hơn nhiều bây giờ. Chuyện lạ.
Nikhil Arora

7

Chúng tôi chỉ sử dụng SubClass mở rộng SuperClass khi lớp con muốn sử dụng một số chức năng (phương thức hoặc biến thể hiện) đã được khai báo trong SuperClass hoặc nếu tôi muốn sửa đổi một chút chức năng của SuperClass (ghi đè phương thức). Nhưng giả sử, ví dụ tôi có một lớp Animal ( SuperClass ) và một lớp Dog ( SubClass ) và có một vài phương thức mà tôi đã định nghĩa trong lớp Animal, vd. doEat (); , doS ngủ (); ... và nhiều thứ khác nữa.

Bây giờ, lớp Dog của tôi có thể đơn giản mở rộng lớp Animal, nếu tôi muốn con chó của tôi sử dụng bất kỳ phương thức nào được khai báo trong lớp Animal, tôi có thể gọi các phương thức đó bằng cách tạo một đối tượng Dog. Vì vậy, theo cách này tôi có thể đảm bảo rằng tôi có một con chó có thể ăn và ngủ và làm bất cứ điều gì khác mà tôi muốn con chó làm.

Bây giờ, hãy tưởng tượng, một ngày nọ, một số người yêu Mèo bước vào không gian làm việc của chúng tôi và cô ấy cố gắng mở rộng lớp Thú (mèo cũng ăn và ngủ). Cô tạo một đối tượng Cat và bắt đầu gọi các phương thức.

Nhưng, giả sử, ai đó cố gắng tạo ra một đối tượng của lớp Thú. Bạn có thể cho biết một con mèo ngủ như thế nào, bạn có thể cho biết một con chó ăn như thế nào, bạn có thể cho biết một con voi uống như thế nào. Nhưng nó không có ý nghĩa gì trong việc tạo ra một đối tượng của lớp Thú. Bởi vì nó là một khuôn mẫu và chúng tôi không muốn có bất kỳ cách ăn uống chung nào.

Vì vậy, thay vào đó, tôi sẽ thích tạo một lớp trừu tượng mà không ai có thể khởi tạo nhưng có thể được sử dụng làm mẫu cho các lớp khác.

Vì vậy, để kết luận, Giao diện không là gì ngoài một lớp trừu tượng (một lớp trừu tượng thuần túy) không chứa các triển khai phương thức mà chỉ có các định nghĩa (các mẫu). Vì vậy, bất cứ ai thực hiện giao diện chỉ cần biết rằng họ có các mẫu doEat (); và doS ngủ (); nhưng họ phải định nghĩa doEat () của riêng họ ; và doS ngủ (); phương pháp theo nhu cầu của họ.

Bạn chỉ mở rộng khi bạn muốn sử dụng lại một phần của SuperClass (nhưng hãy nhớ, bạn luôn có thể ghi đè các phương thức của SuperClass theo nhu cầu của bạn) và bạn thực hiện khi bạn muốn các mẫu và bạn muốn tự xác định chúng (theo nhu cầu của bạn).

Tôi sẽ chia sẻ với bạn một đoạn mã: Bạn thử nó với các bộ đầu vào khác nhau và xem kết quả.

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

}


}

Giao diện được xác định :

public interface AnimalInterface {

public void eating();

}


interface Herbi {

public void herbiEating();

}

7

Cả hai từ khóa đều được sử dụng khi tạo lớp mới của riêng bạn bằng ngôn ngữ Java.

Sự khác biệt: implementscó nghĩa là bạn đang sử dụng các thành phần của Giao diện Java trong lớp của mình. extendscó nghĩa là bạn đang tạo một lớp con của lớp cơ sở mà bạn đang mở rộng. Bạn chỉ có thể mở rộng một lớp trong lớp con của mình, nhưng bạn có thể triển khai nhiều giao diện như bạn muốn.

Tham khảo trang tài liệu oracle trên giao diện để biết thêm chi tiết.

Điều này có thể giúp làm rõ giao diện là gì và các quy ước xung quanh việc sử dụng chúng.


7

Trong các thuật ngữ đơn giản nhất, phần mở rộng được sử dụng để kế thừa từ một lớpthực hiện được sử dụng để áp dụng một giao diện trong lớp của bạn

mở rộng :

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

thực hiện :

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

nếu bạn vẫn còn nhầm lẫn, hãy đọc bài này: https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html https://docs.oracle.com/javase/tutorial/java/IandI/USEinterface.html


5

Các lớp họcGiao diện đều là hợp đồng . Họ cung cấp các phương thức và thuộc tính các phần khác của ứng dụng dựa vào.

Bạn xác định một giao diện khi bạn không quan tâm đến các chi tiết thực hiện của hợp đồng này. Điều duy nhất cần quan tâm là hợp đồng (giao diện) tồn tại.

Trong trường hợp này, bạn để nó đến lớp thực hiện giao diện để quan tâm đến các chi tiết về cách thực hiện hợp đồng. Chỉ các lớp có thể thực hiện giao diện.

gia hạn được sử dụng khi bạn muốn thay thế chi tiết của hợp đồng hiện tại. Bằng cách này, bạn thay thế một cách để thực hiện hợp đồng bằng một cách khác. Các lớp có thể mở rộng các lớp khác và giao diện có thể mở rộng các giao diện khác.


3

Extendsđược sử dụng khi bạn muốn các thuộc tính của lớp / giao diện cha mẹ trong lớp / giao diện con của bạn và implementsđược sử dụng khi bạn muốn các thuộc tính của một giao diện trong lớp của bạn.

Thí dụ:

  1. Mở rộng sử dụng lớp

    lớp Phụ huynh {

    }

    lớp Con mở rộng Cha mẹ {

    }

  2. Mở rộng sử dụng giao diện

    giao diện Cha mẹ {

    }

    Giao diện Con mở rộng Cha mẹ {

    }

  3. Thực hiện

giao diện A {

}

lớp B thực hiện A {

}

Kết hợp mở rộng và thực hiện

interface A{

}

class B

{

}

class C implements A,extends B{

}

2

kéo dài

  • lớp chỉ mở rộng một lớp
  • giao diện mở rộng một hoặc nhiều giao diện

thực hiện

  • lớp thực hiện một hoặc nhiều giao diện
  • giao diện 'không thể' thực hiện bất cứ điều gì

các lớp trừu tượng cũng hoạt động như lớp, với phần mở rộng và thực hiện


0

Hai từ khóa này được gắn trực tiếp với Kế thừa, đó là một khái niệm cốt lõi của OOP. Khi chúng ta thừa hưởng một số lớp khác lớp chúng ta có thể sử dụng kéo dài nhưng khi chúng ta sẽ thừa hưởng một số giao diện đến lớp, chúng ta không thể sử dụng kéo dài chúng ta nên sử dụng dụng cụ và chúng tôi sử dụng có thể kéo dài từ khóa để giao diện kế thừa từ giao diện khác.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.