01/10/2018, 08:40
1 Số câu hỏi về OOP mong được giải đáp
em vừa học xong về oop có 1 vài thắc mắc thế này
- ta có thể nói inteface là 1 class thuần ảo ( abstract ) được không ??
- điểm khác biệt giữa abstract và inteface có phải là inteface có thể giải quyết vấn đề đa thừa kế , cho nên khi sử dụng nó để thể hiện tính đa hình sẽ tốt hơn abstract class ( 1 đối tượng có thể có nhiều kiểu )
- mình thấy người ta hay dùng inteface và abstract class để khai báo 1 kiểu chung cho các class có cùng chức năng hay cùng loại , vậy có thể dùng inteface để thay thế cho abstract được không??
Bài liên quan
Anh thấy em nên tìm hiểu kỹ vấn đề cơ bản trước.
Mọi người cứ so sánh thành ra rối. Nghĩ lung tung, học từng cái rành rồi mới so sánh thì rõ như ban ngày thôi.
Sau đó nghiên cứu các ví dụ căn bản em sẽ tự trả lời được câu hỏi của mình. Rất nhiều diễn đàn tiếng Anh hướng dẫn vô cùng dễ hiểu và ngôn ngữ sử dụng rất phổ thông về vấn đề này. Nếu em làm được C# anh khuyên em nên đọc trên C# Corner vì trang này hướng dẫn rất nhẹ nhàng, code dễ hiểu.
giống câu nói của thầy mh, thêm dùng nó như thế nào nữa :v ,
Không, ngược lại thì đúng.
Không đúng. Đa kế thừa là lớp con có tất cả các đặc điểm và khả năng sử dụng các phương thức của các lớp cha, còn interface rằng buộc về phương thức. Vậy nếu đa kế thừa từ nhiều lớp cha có cùng phương thức, cùng thuộc tính thì lớp con quyết định thế nào?
abstract
dùng để tạo thiết lập chung, các lớp con bị ép theo một dòng máu, không linh hoạt.interface
chỉ rằng buộc về phương thức của nhóm, nên hoàn toàn linh hoạt.Always Code To Interfaces.
Tham khảo khóa học này để tìm hiểu rõ hơn về các đặc tính và bản chất của OOP: https://kodemate.com/series/phat-trien-tu-duy-lap-trinh-huong-doi-tuong-voi-java
cảm ơn bạn nhiều…
sao ở đây : http://gockinhnghiem.com/2015/07/12/abstract-class-vs-interface/
nó lại ghi là inteface giải quyết được vấn đề đa thừa kế nhỉ , mình cũng cảm thấy sai khi nói inteface là đa thừa kế vì nó sử dụng từ implement là bổ sung chứ không phải từ extend
nếu mục đích tạo ra abstract class là để tạo thiết lập chung cho các class con , vậy mục đích khi người ta tạo ra interface là gì ?
thì em đã đọc và tự suy nghĩ theo ý của mình ko biết đúng hay ko nên mới lên đây hỏi , chứ dốt mà còn giấu nữa thì bao giờ mới giỏi được ??
2 . Đúng, vì 1 class trong Java thừa kế được từ nhiều interface nên gọi là giải quyểt được vụ đa thừa kế.
vì sử dụng interface nên chính các lớp con sẽ định nghĩa các phương thức đó , còn interface chỉ chứa các phương thức ảo và interface không thể tạo thể hiện được ( 2 điều này đã giải quyết được câu hỏi trên ) , và ở đây interface nó giúp ta loại bỏ mặt hạn chế của đa thừa kế vừa giúp ta có được những tính chất tốt của đa thừa kế (
Interface has 2 meanings or functions in JAVA
Tham khảo bài toán diamond problem.
Interface has only one and only one mean: to morph into anything we want it to behave correspondingly.
Biết ngay, đi sâu vô cái vụ này mất thời gian tranh luận lắm. Vẫn hóng để anh em làm rõ luôn mai mốt khỏi bàn nữa.
Thả hết tym cho trả lời có đầu tư và đúng lý thuyết.
Mình nghĩ @Hung_Nguyen12 trả lời chuẩn rồi. Còn vụ tranh luận đa thừa kế hay thuần ảo … theo mình không quan trọng lắm ^^ (hầu hết các tài liệu đều gọi interface là thuần abstract và dùng cho vụ đa thừa kế).
Còn vụ what, why, when thì mình giải thích qua 1 chút ở 1 số case
Case1: Giả sử bạn viết CRUD cho product
Giờ bạn muốn làm unit-test thì sao? Bạn sẽ tạo ra 1 p = new Product(); //fake. Thế nhưng nếu 1 người nào đó dùng hàm của bạn, nhưng không muốn bị bó buộc vào object Product đó, vì họ chẳng biết Product cần phải được tạo ra như thế nào (giả sử lib của bạn đã được compile). So sánh với:
Giờ mình gom những cái gì thực sự cần thiết ra 1 interface, họ có thể tự truyền 1 new MockProduct implement IProduct là được, dễ dàng hơn rất nhiều phải không? Nguyên lý này được gọi là Liskov Duck (chữ L trong SOLID), nghĩa là bạn thiết kế ra 1 con vịt tiêu chuẩn mà có thể gắn pin AA, con thỏ, con ó … vào được, miễn là pin đó phù hợp với thiết kế IPin. Việc gom tạo interface cũng giúp người sử dụng lib dễ dàng hiểu các API nào mình expose cho họ, cũng giống như bạn cầm cái điều khiển quạt, bạn bấm 1,2,3 … chứ đâu cần biết trong cái điều khiển đó, nguyên lý hoạt động ra sau (ví dụ, bấm 1, tạo xung điện, kết nối bộ phần phát hồng ngoại, gửi tín hiệu hồng ngoại, quạt nhận tín hiệu hồng ngoại, chuyển đổi xung, biến trở ngắt để cuộn cảm chuyển mạch sang cảm ứng điện mới …Who cares?)
Case2: trong lập trình sự kiện (event-driven), giả sử sự kiện click
Việc truyền 1 class implement OnClickListener vì trong cái event-loop nghe sự kiện, mình sẽ phải gọi cái action xử lý khi có sự kiện đó. Lúc đó, mình gọi action nào nếu mình không qui định trong inteface. Việc qui định click function sẽ giúp mình thống nhất cách gọi (chứ ông thì đặt click, ông đặt push, … mình phải wrap hết các trường hợp đó có mà a ma toi)
Case3: vụ đa thừa kế (thực tế thì thừa kế mỗi tên hàm, chứ nội dung thì có thừa kế đâu). Ví dụ mình muốn viết 1 collection.
Rõ ràng mình cần MyCollection của mình phải iterate được, phải move qua move lại giữa các element, … thế nên mình implement các Interface chuẩn thì: thứ nhất không bỏ sót tính năng, thứ hai collection này sau có thể dùng như các collection chuẩn khác (người dùng lib đỡ phải học)
Interface được dùng trong rất nhiều design pattern kiểu Protocol Oriented (tức là mình chỉ cần hiểu giao thức, còn phía trong đâu cần biết) như Command, Repository …
Còn abstract class thì mình lấy case này nhé, bạn muốn thiết kế 1 Gateway package (thanh toán). Có rất nhiều gateway như Paypal, GoogleCheckout, … Có tới hàng nghìn gateway, và bất cứ gateway nào cũng có các function kiểu như getAccInfo, draw, deposit, transferInternal …
Thế nhưng các function như getAccInfo hay tranferInternal ở cổng nào cũng giống nhau, chỉ là lấy thông tin 1 acc hay chuyển tiền từ 1 acc nào đó sang 1 acc khác, … Còn các funftion kia thì nghiệp vụ khác, mỗi ngân hàng 1 kiểu. … Nếu thiết kế Interface thì sẽ bị duplicate các function giống nhau. Thế nên thiết kế abtract hợp lý hơn
abstract chính là kiểu lai giữa class thuần và interface thuần (mixed). Thường abstract hay dùng trong Factory pattern. Ví dụ, mình gọi Paypal p = GatewayBuilder.build(‘Paypal’);
Còn vụ từ khoá implements hay extends chỉ là để bộ compiler hiểu thôi, chứ vào memory thì là object code hết (1 số ngôn ngữ còn chẳng có từ khoá này, cứ dấu : mà tương cho đỡ phải viết nhiều chữ ^^). Với lại, chả nhẽ viết extends and implement Gateway (abstract) ^^
Cũng như tất cả các ngành sản xuất khác, việc làm abstract (tính trong suốt) thường là trending. Các tầng, các lớp không cần biết các tầng phía dưới thế nào, chỉ cần mày cung cấp đủ data để tao hiển thị (mày có lấy từ MySQL, từ Webservice, rồi mày có dungf CRUD hay CQ-RS thì kệ bố mày, tao méo quan tâm ^^). Ông làm core thì cứ làm core, tao làm shell thì cứ đúng chuản tao làm, mày chưa xong thì tao cứ mặc định là data sẽ là như thế để code, chứ dek ai đợi được ông code xong.
Đấy, việc design theo chuẩn giúp làm //, giúp isolate công việc của nhau, của các tầng. Ông sản xuất giao hàng, ông kho chỉ cần biết là hàng nó kích thước vậy, khối lượng vậy rồi bố trí lên kệ, ông giao nhận thì chỉ cần nhận gói hàng, xem ký hiệu dễ vỡ hay … gì đó rồi giao cho khách … Mỗi ông 1 công đoạn, không cần biết công việc quá của nhau, chỉ cần biết in-out là đủ.
Thế giới cần những người như bạn.
khá rõ ràng , thanks bạn …
Thực ra hôm qua vừa ngủ gật, vừa viết vội nên cũng nhiều chỗ bị lỗi typo. Thank mọi người đã động viên ^^
Dùng fully qualified name được mà nhỉ
Nếu đã là kế thừa thì phải biết chắc ghi gọi một method từ lớp cha thì phải biết thực thi method nào; nếu truy xuất thế này thì lại ko đúng bản chất kế thừa.
Vì thế mà trong Java, đa kế thừa ko thực hiện được. Cách giải quyết là dùng interface cho phép tạo rằng buộc về khả năng trong từng nhóm implementation.
Trong C#, tương tự như Java, nhưng thay vì dùng chung dấu
:
cho cả inheritance và interface contract, nên nếu chỉ tìm hiểu qua C# sẽ rất hay bị hiểu nhầm là đa kế thừa.1 . ta có thể nói inteface là 1 class thuần ảo ( abstract ) được không ??
Không vì interface là interface , abstract class là abstract class
2. điểm khác biệt giữa abstract và inteface có phải là inteface có thể giải quyết vấn đề đa thừa kế , cho nên khi sử dụng nó để thể hiện tính đa hình sẽ tốt hơn abstract class ( 1 đối tượng có thể có nhiều kiểu )
Đúng là interface khác abstract class ở chỗ nó cho đa kế thừa , nhưng chưa đủ . Interface không chứa các thuộc tính và phương thức có nội dung còn abstract class thì có , do vậy nếu chỉ dùng interface mà không dùng abstract class thì sẽ phải khởi tạo các thuộc tính giống nhau và các phương thức có nội dung nhiều lần.
3.mình thấy người ta hay dùng inteface và abstract class để khai báo 1 kiểu chung cho các class có cùng chức năng hay cùng loại , vậy có thể dùng inteface để thay thế cho abstract được không??