Câu hỏi Giao diện vs Lớp trừu tượng (OO chung)


Gần đây tôi đã có hai cuộc phỏng vấn qua điện thoại, nơi tôi được hỏi về sự khác biệt giữa một Giao diện và một lớp Tóm tắt. Tôi đã giải thích mọi khía cạnh của họ mà tôi có thể nghĩ đến, nhưng có vẻ như họ đang chờ tôi đề cập đến một cái gì đó cụ thể, và tôi không biết nó là gì.

Theo kinh nghiệm của tôi, tôi nghĩ những điều sau là đúng. Nếu tôi thiếu một điểm chính, xin vui lòng cho tôi biết.

Giao diện:

Mỗi phương thức duy nhất được khai báo trong một Giao diện sẽ phải được thực hiện trong lớp con. Chỉ các sự kiện, đại biểu, thuộc tính (C #) và phương thức có thể tồn tại trong một giao diện. Một lớp có thể thực hiện nhiều Giao diện.

Lớp trừu tượng:

Chỉ các phương thức trừu tượng phải được thực hiện bởi lớp con. Một lớp Tóm tắt có thể có các phương thức bình thường với việc triển khai. Lớp trừu tượng cũng có thể có các biến lớp bên cạnh Sự kiện, Đại biểu, Thuộc tính và Phương thức. Một lớp chỉ có thể thực hiện một lớp trừu tượng chỉ do không tồn tại đa thừa kế trong C #.

  1. Sau tất cả, người phỏng vấn đã đưa ra câu hỏi "Nếu bạn có một lớp Tóm tắt chỉ với các phương pháp trừu tượng thì nó sẽ khác với giao diện như thế nào?" Tôi không biết câu trả lời nhưng tôi nghĩ đó là thừa kế như đã nói ở trên phải không?

  2. Một người phỏng vấn khác hỏi tôi điều gì xảy ra nếu bạn có một biến Công khai bên trong giao diện, nó sẽ khác với Tóm tắt như thế nào? Tôi nhấn mạnh rằng bạn không thể có một biến công cộng bên trong một giao diện. Tôi không biết anh ấy muốn nghe gì nhưng cũng không hài lòng.

Xem thêm:


1198
2018-04-17 16:42


gốc


Trong khi tôi nghĩ rằng điều quan trọng là phải biết sự khác biệt giữa hai, đây không phải là một câu hỏi phỏng vấn tốt, imo. Trừ khi công việc đã được viết một cuốn sách về các chủ đề OO. Bạn tốt hơn không làm việc cho những con dơi ding. - Alan
@ Alan: Tôi thực sự thích điều này như một câu hỏi phỏng vấn, nhưng tôi sẽ không hound ai đó theo cách này - tôi có thể đăng nó giống như "Bạn sẽ chọn giao diện trên lớp cơ sở trừu tượng khi xác định cấu trúc phân cấp ở đâu? ", hoặc một cái gì đó tương tự. - Reed Copsey
Có lẽ họ là sau một câu trả lời tập trung hơn thiết kế ... mặc dù như bạn tôi đã có thể coi nó như một câu hỏi kỹ thuật. - CurtainDog
Những điểm khác biệt tuyệt vời ở đây: mindprod.com/jgloss/interfacevsabstract.html - Rajat_R
@Kave: I insisted you can't have a public variable inside an interface. Tôi nghĩ giao diện có thể có biến công khai. Trong các biến thực tế trong giao diện được tự động công khai và cuối cùng. - a Learner


Các câu trả lời:


Trong khi câu hỏi của bạn cho thấy nó là "chung OO", nó thực sự có vẻ tập trung vào việc sử dụng .NET của các thuật ngữ này.

Trong .NET (tương tự cho Java):

  • giao diện có thể không có trạng thái hoặc triển khai
  • một lớp thực hiện một giao diện phải cung cấp một thực hiện tất cả các phương thức của giao diện đó
  • các lớp trừu tượng có thể chứa trạng thái (các thành viên dữ liệu) và / hoặc việc thực hiện (các phương thức)
  • các lớp trừu tượng có thể được thừa hưởng mà không cần triển khai các phương thức trừu tượng (mặc dù một lớp dẫn xuất như vậy là trừu tượng)
  • các giao diện có thể được thừa kế, các lớp trừu tượng có thể không (đây có lẽ là lý do chính để giao diện tồn tại riêng biệt với các lớp abtract - chúng cho phép thực hiện nhiều thừa kế loại bỏ nhiều vấn đề của MI chung).

Theo thuật ngữ chung của OO, sự khác biệt không nhất thiết phải được xác định rõ ràng. Ví dụ, có các lập trình viên C ++ có thể chứa các định nghĩa cứng nhắc tương tự (giao diện là một tập con nghiêm ngặt của các lớp trừu tượng không thể triển khai), trong khi một số có thể nói rằng một lớp trừu tượng với một số triển khai mặc định vẫn là một giao diện hoặc không trừu tượng lớp vẫn có thể định nghĩa một giao diện.

Thật vậy, có một thành ngữ C ++ được gọi là Giao diện phi ảo (NVI), nơi các phương thức công khai là các phương thức không phải ảo mà 'thunk' cho các phương thức ảo riêng tư:


632
2018-04-17 17:18



Cảm ơn bạn. Tôi nghĩ rằng kể từ khi câu trả lời của bạn đề cập đến trạng thái + tổng quan tốt về tất cả phần còn lại, tôi đánh dấu phản hồi của bạn là câu trả lời cuối cùng. Bạn nói đúng Tôi đã yêu cầu OO nói chung, kể từ khi người phỏng vấn đầu tiên của tôi hỏi OO nói chung, nhưng vì tôi là một anh chàng C #, tôi có xu hướng quên điều đó. ;-) Cũng nhờ lời giải thích C ++, như mọi khi c ++ là tâm thổi. - Houman
Tôi nghĩ điểm mấu chốt trong lời giải thích mà Michael cung cấp là khi thực hiện một giao diện, bạn PHẢI thực hiện tất cả các thành viên trong giao diện, nhưng khi kế thừa từ một lớp trừu tượng, nó KHÔNG YÊU CẦU bởi một lớp con - Guillermo Gomez
1: Tôi muốn sẵn sàng đặt cược rằng những con khỉ lưu trữ cuộc phỏng vấn thậm chí không nhận ra rằng các ngôn ngữ khác thực hiện OO khác nhau. - Lightness Races in Orbit
@ JL Tôi không thấy vấn đề nằm ở đâu. Dường như bạn có phương pháp trừu tượng bị nhầm lẫn với lớp trừu tượng. trừu tượng phương pháp không có triển khai. Tuy nhiên, bên trong một trừu tượng lớp học, một số các phương thức có thể trừu tượng (nghĩa là không có triển khai) trong khi một số khác thực sự có thể thực hiện. - xji
Lưu ý rằng trong Java 8, bây giờ bạn có thể có các phương thức mặc định và các phương thức tĩnh trong các giao diện có nghĩa là các giao diện Java có thể thực hiện. Tài liệu tham khảo đây. Rõ ràng bạn đã giới thiệu chủ yếu đến .NET, vì vậy đây chỉ là một quan sát đề cập đến Java. - davtom


Tương tự như thế nào: khi tôi ở trong Không quân, tôi đã đi huấn luyện phi công và trở thành phi công của Không quân Hoa Kỳ (USF). Vào thời điểm đó tôi không đủ điều kiện để bay bất cứ thứ gì, và phải tham dự khóa đào tạo loại máy bay. Khi tôi đủ điều kiện, tôi là một phi công (lớp Tóm tắt) và một phi công C-141 (lớp bê tông). Tại một trong các nhiệm vụ của tôi, tôi được bổ nhiệm thêm một nhiệm vụ: Nhân viên an toàn. Bây giờ tôi vẫn là phi công và phi công C-141, nhưng tôi cũng đã thực hiện các nhiệm vụ của Sĩ quan An toàn (tôi đã thực hiện ISafetyOfficer, vì vậy để nói). Một phi công không phải là một sĩ quan an toàn, những người khác cũng có thể làm như vậy.

Tất cả các phi công của Hoa Kỳ phải tuân theo một số quy định của Không quân, và tất cả phi công C-141 (hoặc F-16, hoặc T-38) đều là phi công USAF. Bất cứ ai cũng có thể là nhân viên an toàn. Vì vậy, để tóm tắt:

  • Thí điểm: lớp trừu tượng
  • C-141 Pilot: lớp bê tông
  • ISafety Officer: giao diện

lưu ý thêm: điều này có nghĩa là một sự tương tự để giúp giải thích khái niệm, không phải là một khuyến nghị mã hóa. Xem các ý kiến ​​khác nhau dưới đây, các cuộc thảo luận là thú vị.


756
2017-08-30 04:40



Tôi thực sự thích sự tương tự này, nó sử dụng một ví dụ đơn giản để giải thích một chủ đề hơi phức tạp - Kevin Bowersox
Đây là cách tốt nhất để hiểu thuật ngữ OO phức tạp. Tóm lại, tất cả các lý thuyết chỉ có giá trị khi bạn có thể sử dụng nó thực tế. @Jay bạn rexample là thực sự dễ dàng để nắm bắt sau đó một số điểm bullet (chủ yếu là thâm nhập tâm thay vì được hấp thụ!) - v s
Tôi vẫn còn chút bối rối. Giả sử, bây giờ bạn đã đạt được chứng chỉ F-16 và T-38, vì vậy giờ đã học Jay không thể kế thừa từ nhiều lớp (thí điểm C-141, phi công F-16 và phi công T-38), điều đó có nghĩa là các lớp nào sẽ trở thành giao diện? Cảm ơn - Alex Okrushko
Rất nhiều người đã đưa ra một bình luận +1 cho Alex, vì nó cho thấy một số điểm yếu trong ví dụ này. Đầu tiên, tôi sẽ nói rằng Jay sẽ là một ví dụ của C-141Pilot chứ không phải là lớp riêng của nó. Ngoài ra, vì trong USAF 99% của tất cả các phi công chỉ đủ điều kiện trong một máy bay tại một thời điểm (FCF và phi công thử nghiệm là ngoại lệ đáng chú ý) tôi đã không xem xét nhiều bằng cấp và làm thế nào mà có thể được thực hiện. Như tôi đã biết về một phi công, 50 năm trước, đã đủ điều kiện trong 25 chiếc máy bay khác nhau cùng một lúc, tôi nghĩ rằng ví dụ như thế nào chúng ta KHÔNG muốn sử dụng nhiều thừa kế. - Jay
Vì không có khả năng một phi công bay nhiều máy bay cùng một lúc, đây sẽ là cơ hội tốt để thực hiện mô hình chiến lược. Một phi công sẽ có một bộ sưu tập các chứng chỉ, và chọn một chứng nhận đúng lúc chạy. Các chứng chỉ sẽ được mã hóa là các hành vi sẽ triển khai giao diện IFlyPlane, với các phương thức TakeOff, Land, Eject. - Michael Blackburn


Tôi nghĩ câu trả lời mà họ đang tìm kiếm là sự khác biệt triết học cơ bản hay OPPS.

Kế thừa lớp trừu tượng được sử dụng khi lớp dẫn xuất chia sẻ các thuộc tính cốt lõi và hành vi của lớp trừu tượng. Loại hành vi thực sự xác định lớp.

Mặt khác, giao diện thừa kế được sử dụng khi các lớp chia sẻ hành vi ngoại vi, các lớp không nhất thiết phải định nghĩa lớp dẫn xuất.

Ví dụ: Xe hơi và xe tải chia sẻ rất nhiều đặc tính và hành vi cốt lõi của lớp trừu tượng ô tô, nhưng chúng cũng chia sẻ một số hành vi ngoại vi như tạo ra khí thải mà thậm chí các lớp không phải ô tô như Drillers hoặc PowerGenerators chia sẻ và không nhất thiết phải định nghĩa xe hơi hoặc xe tải , vì vậy Car, Truck, Driller và PowerGenerator đều có thể chia sẻ cùng một giao diện IExhaust.


194
2017-08-31 12:09



Tôi nghĩ rằng một sự tương tự tốt hơn sẽ là "usesFuel" sẽ hiển thị hợp đồng bản chất của giao diện. - Pureferret
@Pureferret nếu accelerate là một phần của hành vi cốt lõi của lớp trừu tượng ô tô, sau đó tôi không thể nói accelerate cho thấy hợp đồng Thiên nhiên. bản chất hợp đồng là gì? tại sao từ này contract giới thiệu bất cứ khi nào chúng ta nói về interface? - overexchange
@overexchange vì thường là giao diện chỉ nơi hai 'bề mặt' gặp nhau, nhưng hợp đồng từ ngụ ý có một thỏa thuận làm sao hai 'bề mặt' gặp nhau. Nó không có ý nghĩa (ít nhất là với tôi) mà tạo ra khí thải là một cái gì đó bạn 'đồng ý về'. Nhưng nó có ý nghĩa (một lần nữa với tôi) mà bạn có thể đồng ý về việc cần phải sử dụngFuel. - Pureferret
@Pureferret tôi đã nêu ra một truy vấn tại liên kết cho cùng - overexchange
@Pureferret nếu interface cần phải có hành vi ngoại vi, vậy thì tại sao public interface List<E> extends Collection<E> {} được thiết kế để mô tả hành vi cốt lõi của list? điều này thực sự mâu thuẫn với câu trả lời của prasun. Cả hai Collection<E> và List<E> là các giao diện ở đây. - overexchange


Ngắn: Các lớp trừu tượng được sử dụng cho Mô hình hóa một hệ thống phân cấp lớp của các lớp tìm kiếm tương tự (Ví dụ: Động vật có thể là lớp trừu tượng và Con người, Sư tử, Hổ có thể là các lớp có nguồn gốc cụ thể)

Giao diện được sử dụng cho Giao tiếp giữa 2 lớp tương tự / không tương tự không quan tâm đến loại giao diện triển khai lớp (ví dụ: Chiều cao có thể là thuộc tính giao diện và có thể được thực hiện bởi Con người, Xây dựng, Cây. Không quan trọng nếu bạn có thể ăn, bạn có thể bơi bạn có thể chết hoặc bất cứ điều gì .. nó chỉ quan trọng một điều mà bạn cần phải có Chiều cao (thực hiện trong lớp bạn)).


163
2018-04-05 09:53



Tôi thực sự thích câu trả lời này bởi vì đôi khi khó trả lời "cái gì" khác nhau giữa mọi thứ bằng cách nhìn vào một thứ trừu tượng hơn như ý định, thay vì chỉ kết cấu (như cấu trúc, một giao diện và một lớp trừu tượng thuần túy là khá nhiều điều tương tự). - LostSalad
Thật dễ dàng để liệt kê những gì một lớp trừu tượng so với một giao diện có thể làm bằng một ngôn ngữ cụ thể nhưng khó tạo ra một sự trừu tượng để đưa ra ý nghĩa và trách nhiệm đối tượng và những gì bạn nói hoàn toàn tiếp tục sử dụng khái niệm 2 trong OO. Cảm ơn! - Samuel
Tôi nghĩ đây là câu trả lời hay nhất cho một câu hỏi phỏng vấn :). - Envil
@ dhananjay: tôi thấy cách Chiều cao có thể tách rời khỏi khái niệm lớp Động vật và có thể từ một lớp khác, nhưng chính xác bạn có ý nghĩa gì khi "giao tiếp" giữa các lớp? Nó chỉ đơn giản là chỉ xác định Chiều cao cho lớp riêng của mình, đúng không? - T.T.T.


Có một vài khác biệt khác -

Giao diện không thể có bất kỳ triển khai cụ thể nào. Các lớp cơ sở trừu tượng có thể. Điều này cho phép bạn cung cấp các triển khai cụ thể ở đó. Điều này có thể cho phép một lớp cơ sở trừu tượng thực sự cung cấp một hợp đồng nghiêm ngặt hơn, một giao diện thực sự chỉ mô tả cách một lớp được sử dụng. (Lớp cơ sở trừu tượng có thể có các thành viên không ảo xác định hành vi, cho phép kiểm soát nhiều hơn đối với tác giả lớp cơ sở.)

Có thể triển khai nhiều giao diện trên một lớp. Một lớp chỉ có thể xuất phát từ một lớp cơ sở trừu tượng duy nhất. Điều này cho phép hệ thống phân cấp đa hình sử dụng giao diện, nhưng không cho phép các lớp cơ sở trừu tượng. Điều này cũng cho phép một giả đa thừa kế sử dụng giao diện.

Các lớp cơ sở trừu tượng có thể được sửa đổi trong v2 + mà không phá vỡ API. Thay đổi đối với giao diện đang phá vỡ các thay đổi.

[C # /. NET cụ thể] Giao diện, không giống như các lớp cơ sở trừu tượng, có thể được áp dụng cho các loại giá trị (cấu trúc). Structs không thể kế thừa từ các lớp cơ sở trừu tượng. Điều này cho phép các hợp đồng hành vi / hướng dẫn sử dụng được áp dụng trên các loại giá trị.


74
2018-04-17 16:46



1 cho điểm quan trọng mà nhiều hơn một giao diện có thể được thực hiện trên một lớp. - cgp
Đó là một lợi thế thực sự đối với các giao diện trên các lớp cơ sở trừu tượng, IMO. Nếu không, tôi đồng ý với các nguyên tắc thiết kế .NET, bây giờ nói "thích các lớp cơ sở trừu tượng trên các giao diện" - Reed Copsey
Mặc dù, nó sẽ được quan tâm nếu bạn có thể thêm điểm rằng nó cũng là giao diện có thể được áp dụng cho bất kỳ lớp học. - cgp
@altCognito: Đã tìm ra được loại xử lý với đoạn thứ hai. Điều này đã nhắc nhở tôi, mặc dù, giao diện đó hoạt động trên các loại giá trị, vì vậy tôi đã thêm vào đó. - Reed Copsey
Cảm ơn bạn rất nhiều vì mô tả chính xác này. Nó thực sự rất hữu ích. Tôi là người mới ở đây. Thật đáng tiếc là bạn không thể chọn hai câu trả lời là "câu trả lời". Một điều làm tôi bối rối là việc bạn sử dụng lớp Tóm tắt 'cơ bản'. Tất cả các lớp trừu tượng có nghĩa là trở thành một lớp cơ sở của một lớp con. Tại sao đặt tên cho 'cơ sở' thêm? - Houman


Di sản
Hãy xem xét một chiếc xe hơi và một chiếc xe buýt. Họ là hai loại xe khác nhau. Nhưng vẫn còn, họ chia sẻ một số tài sản chung như họ có một tay lái, phanh, bánh răng, động cơ, vv
Vì vậy, với khái niệm thừa kế, điều này có thể được biểu diễn như sau ...

public class Vehicle {
    private Driver driver;
    private Seat[] seatArray; //In java and most of the Object Oriented Programming(OOP) languages, square brackets are used to denote arrays(Collections).
    //You can define as many properties as you want here ...
}

Bây giờ một chiếc xe đạp ...

public class Bicycle extends Vehicle {
    //You define properties which are unique to bicycles here ...
    private Pedal pedal;
}

Và một chiếc xe ...

public class Car extends Vehicle {
    private Engine engine;
    private Door[] doors;
}

Đó là tất cả về Di sản. Chúng tôi sử dụng chúng để phân loại các đối tượng thành các biểu mẫu Cơ sở đơn giản hơn và con cái của chúng như chúng ta đã thấy ở trên.

Lớp trừu tượng

Các lớp trừu tượng là chưa hoàn thiện các đối tượng. Để hiểu nó hơn nữa, chúng ta hãy xem xét tương tự chiếc xe một lần nữa.
Một chiếc xe có thể được điều khiển. Đúng? Nhưng các phương tiện khác nhau được điều khiển theo nhiều cách khác nhau ... Ví dụ: Bạn không thể lái xe giống như lái xe đạp.
Vì vậy, làm thế nào để đại diện cho chức năng lái xe của một chiếc xe? Thật khó để kiểm tra loại xe của nó và lái nó với chức năng riêng của nó; bạn sẽ phải thay đổi lớp Driver một lần nữa và một lần nữa khi thêm một loại xe mới.
Ở đây có vai trò của các lớp và phương thức trừu tượng. Bạn có thể định nghĩa phương thức ổ đĩa là trừu tượng để nói rằng mọi trẻ thừa kế đều phải thực hiện hàm này.
Vì vậy, nếu bạn sửa đổi lớp xe ...

//......Code of Vehicle Class
abstract public void drive();
//.....Code continues

Xe đạp và Xe hơi cũng phải chỉ định cách lái xe. Nếu không, mã sẽ không biên dịch và lỗi được ném.
Trong ngắn hạn .. một lớp trừu tượng là một lớp không hoàn chỉnh một phần với một số chức năng không đầy đủ, mà trẻ em kế thừa phải xác định riêng của họ.

Giao diện Giao diện hoàn toàn không hoàn chỉnh. Họ không có bất kỳ tài sản. Họ chỉ ra rằng trẻ em kế thừa có khả năng làm điều gì đó ...
Giả sử bạn có các loại điện thoại di động khác nhau với bạn. Mỗi người trong số họ có những cách khác nhau để thực hiện các chức năng khác nhau; Ví dụ: gọi một người. Nhà sản xuất điện thoại chỉ định cách thực hiện. Ở đây điện thoại di động có thể quay số - tức là, nó có thể quay số. Hãy đại diện cho điều này như một giao diện.

public interface Dialable {
    public void dial(Number n);
}

Ở đây, nhà sản xuất của Dialable định nghĩa cách quay số. Bạn chỉ cần cung cấp cho nó một số để quay số.

// Makers define how exactly dialable work inside.

Dialable PHONE1 = new Dialable() {
    public void dial(Number n) {
        //Do the phone1's own way to dial a number
    }
}

Dialable PHONE2 = new Dialable() {
    public void dial(Number n) {
        //Do the phone2's own way to dial a number
    }
}


//Suppose there is a function written by someone else, which expects a Dialable
......
public static void main(String[] args) {
    Dialable myDialable = SomeLibrary.PHONE1;
    SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....

Bằng cách này sử dụng các giao diện thay vì các lớp trừu tượng, tác giả của hàm sử dụng một nhu cầu Dialable không phải lo lắng về các thuộc tính của nó. Ví dụ: Ứng dụng có màn hình cảm ứng hay bàn phím số không, Đây có phải là điện thoại cố định hoặc điện thoại di động không. Bạn chỉ cần biết nếu nó có thể gọi được; hiện nó kế thừa (hoặc thực hiện) giao diện Dialable.

Và quan trọng hơn, nếu một ngày nào đó bạn có thể quay số bằng một số khác

......
public static void main(String[] args) {
    Dialable myDialable = SomeLibrary.PHONE2; // <-- changed from PHONE1 to PHONE2
    SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....

Bạn có thể chắc chắn rằng mã vẫn hoạt động hoàn hảo vì chức năng sử dụng dialable không (và không thể) phụ thuộc vào các chi tiết khác với các chi tiết được chỉ định trong giao diện Dialable. Cả hai đều thực hiện một giao diện Dialable và đó là điều duy nhất mà chức năng quan tâm.

Giao diện thường được các nhà phát triển sử dụng để đảm bảo khả năng tương tác (sử dụng thay thế lẫn nhau) giữa các đối tượng, khi chúng chia sẻ một chức năng chung (giống như bạn có thể đổi sang điện thoại cố định hoặc điện thoại di động, khi bạn chỉ cần quay số). Tóm lại, các giao diện là một phiên bản trừu tượng đơn giản hơn nhiều, không có bất kỳ thuộc tính nào.
Ngoài ra, lưu ý rằng bạn có thể thực hiện (kế thừa) như nhiều giao diện như bạn muốn nhưng bạn chỉ có thể mở rộng (kế thừa) một lớp cha đơn.

Thêm thông tin Các lớp trừu tượng và giao diện 


63
2018-06-14 13:11



Không đúng là "Giao diện không có bất kỳ thuộc tính nào". - Bigeyes
@Bigeyes, java không cho phép các thuộc tính trong giao diện. Tôi nghĩ nó cũng tương tự ở các ngôn ngữ khác. Bạn có thể giải thích thêm? - fz_salam
Tôi đang đề cập đến C # /. Xin vui lòng xem thí dụ - Bigeyes
@Bigeyes cho C # nơi giao diện có thể có các thuộc tính, không phải là việc giới thiệu lại vấn đề đa thừa kế? Điều gì sẽ xảy ra khi một lớp sử dụng nhiều giao diện đã xác định cùng một thuộc tính? Chỉ cần cảm ơn - stackPusher
@ T.T.T .: Chỉ cần thêm một ví dụ. Xin hãy xem. - fz_salam


Nếu bạn xem xét java như ngôn ngữ OOP để trả lời câu hỏi này, bản phát hành Java 8 gây ra một số nội dung trong câu trả lời ở trên là lỗi thời. Bây giờ giao diện java có thể có các phương thức mặc định với việc triển khai thực hiện cụ thể.

Oracle trang mạng cung cấp sự khác biệt chính giữa interface và abstract lớp học.

Cân nhắc sử dụng các lớp trừu tượng nếu :

  1. Bạn muốn chia sẻ mã giữa một số lớp liên quan chặt chẽ.
  2. Bạn mong đợi rằng các lớp mở rộng lớp trừu tượng của bạn có nhiều phương thức hoặc trường phổ biến, hoặc yêu cầu các công cụ sửa đổi truy cập ngoài công khai (như bảo vệ và riêng tư).
  3. Bạn muốn khai báo các trường không tĩnh hoặc không phải cuối cùng.

Xem xét sử dụng giao diện nếu :

  1. Bạn hy vọng rằng các lớp không liên quan sẽ triển khai giao diện của bạn. Ví dụ: nhiều đối tượng không liên quan có thể triển khai Serializable giao diện.
  2. Bạn muốn xác định hành vi của một kiểu dữ liệu cụ thể, nhưng không quan tâm đến ai thực hiện hành vi của nó.
  3. Bạn muốn tận dụng lợi thế của nhiều loại thừa kế.

Nói một cách đơn giản, tôi muốn sử dụng

giao diện: Để thực hiện một hợp đồng bởi nhiều đối tượng không liên quan

lớp trừu tượng: Để thực hiện hành vi giống nhau hoặc khác nhau giữa nhiều đối tượng liên quan

Hãy xem ví dụ mã để hiểu mọi thứ theo cách rõ ràng: Làm thế nào tôi đã giải thích sự khác biệt giữa một giao diện và một lớp trừu tượng?


33
2017-11-27 19:20





Những người phỏng vấn đang sủa một cây kỳ lạ. Đối với các ngôn ngữ như C # và Java, có một sự khác biệt, nhưng trong các ngôn ngữ khác như C ++ thì không có. Lý thuyết OO không phân biệt hai, chỉ là cú pháp của ngôn ngữ.

Lớp trừu tượng là một lớp có cả triển khai và giao diện (các phương thức ảo thuần túy) sẽ được kế thừa. Giao diện thường không có bất kỳ việc thực hiện nào nhưng chỉ có các hàm ảo thuần túy.

Trong C # hoặc Java, một lớp trừu tượng mà không có bất kỳ sự triển khai nào khác với một giao diện chỉ trong cú pháp được sử dụng để kế thừa từ nó và thực tế bạn chỉ có thể kế thừa từ một.


30
2018-04-17 16:48



Tôi đã được hỏi cùng một câu hỏi một tuần trước, tôi không có kinh nghiệm với Java nhưng tôi đã làm việc với C ++ trong một thời gian. Người phỏng vấn không chỉ định ngôn ngữ trước khi đặt câu hỏi, vì vậy tôi chỉ giải thích rằng các giao diện trong trường hợp này là các lớp trừu tượng không có trạng thái hoặc triển khai dưới bất kỳ hình thức nào. Tôi đồng ý rằng đó cũng là một câu hỏi kỳ quặc. - David Cabrera


Bằng cách thực hiện các giao diện, bạn đang đạt được thành phần ("có một" mối quan hệ) thay vì thừa kế ("là một" mối quan hệ). Đó là một nguyên tắc quan trọng cần nhớ khi nói đến những thứ như các mẫu thiết kế mà bạn cần sử dụng các giao diện để đạt được một thành phần của các hành vi thay vì thừa kế.


29
2018-04-17 16:52



Giao diện đạt được, IMO, nhiều hơn một mối quan hệ "Hành vi-as-a". Đóng gói đạt được thành phần tốt hơn so với giao diện. - Reed Copsey
Tôi không nghĩ rằng việc thực hiện các giao diện sẽ đến theo bố cục. - Pavan
Thêm vào đó, giao diện có nhiều khả năng sử dụng để mô tả "khả năng", giống như IDisposable. Nó được sử dụng để chia sẻ chức năng giữa các lớp mà các lớp này "có thể làm" một cái gì đó. Ví dụ khác IFlyable có thể được thực hiện bởi chim và máy bay. Nhưng Bird có thể xuất phát từ Class Creature, nơi airecraft lấy được từ AirCraft. - Peter.Wang


Tôi sẽ giải thích chi tiết về giao diện và lớp Tóm tắt. Nếu bạn biết tổng quan về giao diện và lớp trừu tượng, thì câu hỏi đầu tiên sẽ xuất hiện trong đầu khi chúng ta nên sử dụng Giao diện và khi chúng ta nên sử dụng lớp Tóm tắt. Vì vậy, xin vui lòng kiểm tra dưới đây giải thích về giao diện và lớp trừu tượng.

  1. Khi nào chúng ta nên sử dụng Giao diện?

    nếu bạn không biết về việc triển khai, chúng tôi có đặc điểm yêu cầu thì chúng tôi sẽ đi với Giao diện 

  2. Khi nào chúng ta nên sử dụng Abstract Class?

    nếu bạn biết thực hiện nhưng không hoàn toàn (thực hiện một phần) thì chúng ta đi với lớp Abstract. 

    Giao diện

    mọi phương thức theo mặc định công khai trừu tượng có nghĩa là giao diện là 100% trừu tượng thuần túy.

    trừu tượng

    có thể có phương pháp Bê tông và Phương pháp trừu tượng, phương pháp Bê tông là gì, trong đó có thực hiện trong lớp Tóm tắt,    Một lớp trừu tượng là một lớp được khai báo trừu tượng — nó có thể hoặc không thể bao gồm các phương thức trừu tượng.

    Giao diện

    Chúng tôi không thể tuyên bố giao diện dưới dạng riêng tư, được bảo vệ

    H. Tại sao chúng tôi không tuyên bố Giao diện là riêng tư và được bảo vệ?

    Bởi vì theo mặc định, phương thức giao diện là trừu tượng công khai và do đó lý do mà chúng tôi không khai báo giao diện là riêng tư và được bảo vệ.

    Phương thức giao diện
       chúng tôi cũng không thể tuyên bố giao diện là riêng tư, được bảo vệ, cuối cùng, tĩnh, đồng bộ, gốc .....

    tôi sẽ đưa ra lý do:  tại sao chúng ta không khai báo phương thức đồng bộ bởi vì chúng ta không thể tạo đối tượng của giao diện và đồng bộ hóa đang làm việc trên đối tượng nên lý do con trai mà chúng ta không khai báo phương thức được đồng bộ hóa  Khái niệm thoáng qua cũng không áp dụng được vì công việc tạm thời được đồng bộ hóa.

    trừu tượng 

    chúng ta vui vẻ sử dụng với tĩnh công cộng, riêng tư cuối cùng .... có nghĩa là không hạn chế nào được áp dụng trong trừu tượng.

    Giao diện

    Các biến được khai báo trong Giao diện dưới dạng kết quả tĩnh công khai mặc định, vì vậy chúng tôi cũng không được khai báo biến là riêng tư, được bảo vệ.

    Biến đổi dễ bay hơi cũng không được áp dụng trong giao diện vì biến giao diện là biến cố định cuối cùng và biến cuối cùng, bạn không thể thay đổi giá trị khi gán giá trị vào biến và khi bạn khai báo biến thành giao diện, bạn phải gán biến.

    Và biến biến động là tiếp tục thay đổi để nó là opp. cuối cùng đó là lý do chúng tôi không sử dụng biến biến động trong giao diện.

    trừu tượng

    Biến trừu tượng không cần khai báo public static final.

tôi hy vọng bài viết này hữu ích.


23
2018-05-31 06:33



Lời giải thích tuyệt vời ... +1 từ phía tôi ... - Krishnraj Rana
Tôi không đồng ý với điểm này: Abstract class must have at lease one abstract method. Có thể có lớp Tóm tắt không có phương thức Tóm tắt, miễn là bạn triển khai nó. TÀI LIỆU THAM KHẢO: An abstract class is a class that is declared abstract—it may or may not include abstract methods. NGUỒN THAM KHẢO: docs.oracle.com/javase/tutorial/java/IandI/abstract.html - Devner


Đối với .Net,

Câu trả lời của bạn cho người phỏng vấn thứ hai cũng là câu trả lời cho người đầu tiên ... Các lớp trừu tượng có thể có thực hiện, và trạng thái, các giao diện không thể ...

EDIT: Trên một lưu ý khác, tôi thậm chí sẽ không sử dụng cụm từ 'subclass' (hoặc 'thừa kế' cụm từ) để mô tả các lớp học được 'định nghĩa để thực hiện' một giao diện. Với tôi, một giao diện là định nghĩa của một hợp đồng mà một lớp phải tuân thủ nếu nó được định nghĩa là 'triển khai' giao diện đó. Nó không thừa hưởng bất cứ điều gì ... Bạn phải thêm tất cả mọi thứ cho mình, rõ ràng.


21
2018-04-17 16:48



Vâng! Tiểu bang! Đó là những gì người phỏng vấn thứ hai có nghĩa là với cách kỳ lạ của mình nói "biến công cộng" bên trong một giao diện. gosh! Lớp trừu tượng có thể có trạng thái, giao diện không thể! Và tất cả mọi người đều đồng ý về sự khác biệt giữa cách thức thừa kế của họ, điều mà tôi đã quên đề cập đến nhưng đã tìm ra sau này. :) Cảm ơn mọi người! - Houman
Không chỉ là trạng thái .... Tóm tắt các lớp học có thể có thực hiện. tức là, họ có thể có các phương thức với mã trong chúng thực sự chạy và thực hiện một cái gì đó, được hít vào và được thực hiện bởi các cá thể của các lớp cơ sở ... Không phải như vậy với các giao diện - Charles Bretana
Thậm chí nhiều hơn thế, theo một nghĩa nào đó, các lớp Tóm tắt có thể được khởi tạo, chúng chỉ cần được khởi tạo bằng cách sử dụng định nghĩa lớp dẫn xuất, chứ không phải trực tiếp. Nhưng các biến trạng thái được định nghĩa trong lớp trừu tượng được khởi tạo trong đối tượng được tạo ra bằng cách nạp mới một cá thể của lớp dẫn xuất. Ví dụ này là một thể hiện của lớp trừu tượng cũng như là một thể hiện của lớp dẫn xuất - nó là sau khi tất cả bắt nguồn từ nó. Không có điều này là đúng cho một giao diện. - Charles Bretana
Khi bạn mới tạo một thể hiện của một lớp được định nghĩa để thực hiện một giao diện, nó không phải là một "cá thể" của giao diện đó, tất cả cú pháp làm là trình biên dịch kiểm tra mã cho lớp và đảm bảo mọi hành vi (phương thức, thuộc tính , event, eventHandler, vv) được định nghĩa bởi giao diện đã được thực hiện trong mã cho lớp. - Charles Bretana