Sự khác biệt giữa giao diện và lớp là gì và tại sao tôi nên sử dụng giao diện khi tôi có thể thực hiện các phương thức trực tiếp trong lớp?


117

Tôi biết rằng đây là một câu hỏi rất cơ bản, nhưng một người phỏng vấn đã hỏi tôi một cách rất mánh khóe và tôi bất lực :(

Tôi chỉ biết định nghĩa vật liệu hoặc lý thuyết cho một giao diện và cũng đã triển khai nó trong nhiều dự án tôi đã làm việc. Nhưng tôi thực sự không hiểu tại sao và làm thế nào là hữu ích.

Tôi cũng không hiểu một điều trong giao diện. ví dụ: chúng tôi sử dụng

conn.Dispose();trong khối cuối cùng. Nhưng tôi không thấy rằng lớp đang triển khai hoặc kế thừa lớp IDisposablegiao diện ( SqlConnection). Tôi tự hỏi làm thế nào tôi chỉ có thể gọi tên phương thức. Cũng trong điều tương tự, tôi không hiểu phương thức Dispose hoạt động như thế nào bởi vì, chúng ta cần triển khai phần thân hàm với việc thực hiện riêng cho tất cả các phương thức giao diện. Vậy làm thế nào Giao diện được chấp nhận hoặc đặt tên là hợp đồng? Những câu hỏi này cứ liên tục xuất hiện trong đầu tôi và thật lòng tôi chưa bao giờ thấy bất kỳ chủ đề hay nào có thể giải thích câu hỏi của tôi theo cách mà tôi có thể hiểu.

MSDN như thường lệ trông rất đáng sợ và không có dòng nào rõ ràng cả ( Mọi người, xin lỗi, người đang phát triển cấp cao, tôi cảm thấy mạnh mẽ rằng bất kỳ mã hoặc bài viết nào sẽ đến được tâm trí của bất kỳ ai nhìn thấy nó, do đó, giống như nhiều người khác nói, MSDN không sử dụng ).

Người phỏng vấn nói:

Anh ta có 5 phương thức và anh ta rất vui khi trực tiếp thực hiện nó trong lớp, nhưng nếu bạn phải chọn lớp Trừu tượng hoặc giao diện, bạn chọn phương thức nào và tại sao? Tôi đã trả lời anh ấy tất cả những thứ tôi đọc trong nhiều blog nói về ưu điểm và nhược điểm của cả lớp trừu tượng và giao diện, nhưng anh ấy không bị thuyết phục, anh ấy đang cố gắng hiểu "Tại sao giao diện" nói chung. "Tại sao lớp trừu tượng" nói chung ngay cả khi tôi có thể thực hiện cùng một phương thức chỉ một lần và không thay đổi nó.

Tôi thấy không có nơi nào trong mạng, tôi có thể nhận được một bài viết sẽ giải thích rõ ràng cho tôi về giao diện và chức năng của nó. Tôi là một trong số nhiều lập trình viên, những người vẫn chưa biết về giao diện (tôi biết lý thuyết và phương pháp tôi đã sử dụng) nhưng không hài lòng vì tôi hiểu rõ về nó.


4
Giao diện là một trong những tôi đã đấu tranh để hiểu cũng. Câu hỏi hay.
Brian

4
lập trình cho một hợp đồng trừu tượng chứ không phải là một triển khai cụ thể .... Tóm lại, điều đó có nghĩa là bạn có thể thay thế bất kỳ đối tượng nào thực hiện giao diện khi cần một giao diện.
Mitch Wheat

7
SqlConnectionkế thừa System.ComponentModel.Componentmà thực hiện IDisposable.
Lee

2
@MitchWheat - Đây không phải là một ví dụ, câu hỏi hỏi cách SqlConnectionthực hiện IDisposable.
Lee

Oh Lee, điều đó làm tôi hiểu cảm ơn bạn. Nhưng tôi vẫn không thấy chức năng phương thức "Vứt bỏ" được định nghĩa như thế nào hoặc ở đâu.
Học viên

Câu trả lời:


92

Các giao diện là tuyệt vời khi bạn muốn tạo ra một cái gì đó giống như nó:

using System;

namespace MyInterfaceExample
{
    public interface IMyLogInterface
    {
        //I want to have a specific method that I'll use in MyLogClass
        void WriteLog();       
    }

    public class MyClass : IMyLogInterface
    {

        public void WriteLog()
        {
            Console.Write("MyClass was Logged");
        }
    }

    public class MyOtherClass : IMyLogInterface
    {

        public void WriteLog()
        {
            Console.Write("MyOtherClass was Logged");
            Console.Write("And I Logged it different, than MyClass");
        }
    }

    public class MyLogClass
    {
        //I created a WriteLog method where I can pass as a parameter any object that implements IMyLogInterface.
        public static void WriteLog(IMyLogInterface myLogObject)
        {
            myLogObject.WriteLog(); //So I can use WriteLog here.
        }
    }

    public class MyMainClass
    {
        public void DoSomething()
        {
            MyClass aClass = new MyClass();
            MyOtherClass otherClass = new MyOtherClass();

            MyLogClass.WriteLog(aClass);//MyClass can log, and have his own implementation
            MyLogClass.WriteLog(otherClass); //As MyOtherClass also have his own implementation on how to log.
        }
    }
}

Trong ví dụ của tôi, tôi có thể là một nhà phát triển viết MyLogClassvà các nhà phát triển khác có thể tạo các lớp của họ và khi họ muốn đăng nhập, họ thực hiện giao diện IMyLogInterface. Đó là như họ đã hỏi tôi những gì họ cần thực hiện để sử dụng WriteLog()phương pháp trong MyLogClass. Câu trả lời họ sẽ tìm thấy trong giao diện.


3
Này có vẻ như là một thành phần rất tốt để tôi hiểu, tôi thực sự đánh giá cao nó, cảm ơn rất nhiều :) :)
Học viên

14
Câu hỏi của tôi là nếu bạn đang bắt đầu MyClassMyOtherClasstại sao bạn không gọi đơn giản aClass.WriteLog()tại sao lại thêm bước đó. Việc thực hiện WriteLog()sẽ vẫn khác nhau đối với mỗi lớp nhưng bạn đã có đối tượng, vậy tại sao lại chuyển nó sang một lớp xử lý?
Zach M.

Tôi có thể là nếu bạn đưa ví dụ đăng nhập của mình lên nugget thì việc người khác sử dụng logger của bạn sẽ đơn giản hơn, mà không cần biết chi tiết .. nhưng mặt khác, vẫn không phải là một lớp phổ quát, (tôi có thể viết một giao diện với các mức ghi nhật ký VÀ allert) vẫn chỉ trong phạm vi của bạn. Vì vậy, ngoài bản thân bạn cho những người được hưởng lợi từ nó?
dùng3800527

2
@ZachM. Nếu tôi đúng, câu trả lời có nghĩa là, anh ta sẽ không khởi tạo các lớp, nhưng các nhà phát triển khác sẽ khởi tạo các lớp và chuyển nó dưới dạng tham số cho MyLogClass WriteLogphương thức. Vì vậy, phương pháp của anh ta có thể xử lý bất kỳ đối tượng nào thực hiện IMyLogInterface. Đây là một bài viết thú vị.
shaijut

1
Câu hỏi của tôi là tại sao Giao diện ??? Kịch bản trên cũng có thể đạt được bởi một lớp trừu tượng với tất cả các phương thức trừu tượng.
Abhijit Ojha

52

Một lý do tôi sử dụng giao diện là vì nó làm tăng tính linh hoạt của mã. Giả sử chúng ta có một phương thức lấy một đối tượng của Tài khoản loại lớp làm tham số, chẳng hạn như:

public void DoSomething(Account account) {
  // Do awesome stuff here.
}

Vấn đề với điều này là tham số phương thức được cố định đối với việc triển khai tài khoản. Điều này là tốt nếu bạn sẽ không bao giờ cần bất kỳ loại tài khoản khác. Lấy ví dụ này, thay vào đó sử dụng giao diện tài khoản làm tham số.

public void DoSomething(IAccount account) {
  // Do awesome stuff here.
}

Giải pháp này không cố định đối với việc triển khai, điều đó có nghĩa là tôi có thể chuyển cho nó SuperSavingsAccount hoặc ExclusiveAccount (cả hai đều thực hiện giao diện IAccount) và có hành vi khác nhau cho mỗi tài khoản được triển khai.


45

Giao diện là hợp đồng mà người thực hiện phải tuân theo. Các lớp trừu tượng cho phép các hợp đồng cộng với việc triển khai được chia sẻ - thứ mà Giao diện không thể có. Các lớp có thể thực hiện và kế thừa nhiều giao diện. Các lớp chỉ có thể mở rộng một lớp trừu tượng duy nhất.

Tại sao giao diện

  • Bạn không có triển khai mã mặc định hoặc chia sẻ
  • Bạn muốn chia sẻ hợp đồng dữ liệu (dịch vụ web, SOA)
  • Bạn có các cách triển khai khác nhau cho mỗi người triển khai giao diện ( IDbCommandSqlCommandOracleCommandtriển khai giao diện theo những cách cụ thể )
  • Bạn muốn hỗ trợ nhiều kế thừa .

Tại sao trừu tượng


2
@Silver Tôi đọc hầu hết những gì bạn đã gõ trên blog, nhưng tôi đang cố gắng để hiểu thực tế. Tôi đã thực hiện các dịch vụ WCF, giao diện tiếp xúc (Nhưng đó chỉ là một ứng dụng độc lập không có ngược dòng hoặc hạ lưu). Do đó tôi không thể hiểu đúng về nó mặc dù tôi đã thiết kế và triển khai các giao diện rất tốt. Câu hỏi của tôi là, thực tế, bạn chỉ cần chia sẻ phương thức tên hợp đồng có nghĩa là đúng? LÀM THẾ NÀO LÀ này hữu ích :( Tôi biết nó chỉ lực lượng để thực hiện tất cả các phương pháp, nhưng khác như thế nào Trong bài viết của bạn trên trên giao diện, điểm 2 nói cổ phiếu, phương tiện bạn có thể cho một ví dụ thời gian thực thực tế của điều này?
Học

1
Để có một ví dụ thực tế về giao diện và SOA, chúng tôi chia sẻ Giao diện WCF của chúng tôi ( DataContracts) trong một hội đồng .NET ( ví dụ: Contraction.Shared.dll ) để người tiêu dùng máy khách .NET có thể dễ dàng tương tác bằng cách sử dụngChannelFactory ( tránh tạo mã thông qua Thêm dịch vụ tham khảo, v.v. ) hoặc sử dụng Thêm tham chiếu dịch vụ với các loại được chia sẻ
SliverNinja - MSFT

Nếu, tôi sẽ chỉ khai báo các phương thức trừu tượng bên trong một calss trừu tượng, thì lớp trừu tượng sẽ hoạt động như giao diện, vậy tại sao chúng ta cần giao diện?
Abhijit Ojha

25

nhập mô tả hình ảnh ở đây

Vì vậy, trong ví dụ này, PowerSocket không biết gì về các đối tượng khác. Tất cả các đối tượng đều phụ thuộc vào Power do PowerSocket cung cấp, do đó chúng triển khai IPowerPlug và để chúng có thể kết nối với nó.

Các giao diện rất hữu ích vì chúng cung cấp các hợp đồng mà các đối tượng có thể sử dụng để làm việc cùng nhau mà không cần biết bất cứ điều gì khác về nhau.


Điều này có ý nghĩa, nhưng tôi vẫn đang cố gắng để hiểu, có thể bạn không tạo ra một lớp cơ sở cho PowerSocket và tất cả những thứ khác kế thừa nó nếu cần. Về mặt kỹ thuật Ổ cắm điện không có ý tưởng về các lớp khác.
altaaf.hussein

Tôi nghĩ bởi vì nhiều quyền thừa kế không được phép trong C #
Hugh Seagraves

22

Trong một từ - vì tính đa hình !

Nếu bạn "Lập trình cho một giao diện, không phải là một triển khai" thì bạn có thể đưa các đối tượng khác nhau có chung giao diện (loại) vào phương thức làm đối số. Bằng cách này, mã phương thức của bạn không được kết hợp với bất kỳ triển khai nào của lớp khác, điều đó có nghĩa là nó luôn mở để làm việc với các đối tượng mới được tạo của cùng một giao diện. (Nguyên tắc mở / đóng)

  • Nhìn vào Tiêm phụ thuộc và chắc chắn đọc Mẫu thiết kế - Các yếu tố của phần mềm hướng đối tượng có thể tái sử dụng của GOF.

4

C # không có kiểu gõ vịt - chỉ vì bạn biết một phương thức nhất định được triển khai trên một tập hợp các lớp cụ thể không có nghĩa là bạn có thể đối xử với chúng giống nhau khi gọi phương thức đó. Việc triển khai một giao diện cho phép bạn coi tất cả các lớp thực hiện nó là cùng một loại, liên quan đến những gì giao diện đó định nghĩa.


3
Bạn có thể nhận được loại vịt trong .net4 với kiểu động.
Tony Hopkinson

4

Tôi tin rằng nhiều máu đã đổ ra khi đặt câu hỏi này và nhiều người cố gắng giải quyết vấn đề này bằng cách giải thích các thuật ngữ giống như robot mà không một người bình thường nào có thể hiểu được.

Vì vậy, đầu tiên. để tìm hiểu lý do tại sao giao diện và tại sao trừu tượng, bạn cần phải học chúng để làm gì. Tôi đã học được hai điều này khi áp dụng Lớp học nhà máy. bạn tìm thấy một hướng dẫn tốt về liên kết này

Bây giờ hãy khai thác dựa trên liên kết mà tôi đã đưa ra.

Bạn có lớp Xe có thể thay đổi theo yêu cầu của người dùng (như thêm Xe tải , Xe tăng , Máy bay , v.v.

public class clsBike:IChoice
{
   #region IChoice Members
    public string Buy()
    {
       return ("You choose Bike");
    }
    #endregion
}

public class clsCar:IChoice
{
   #region IChoice Members
    public string Buy()
    {
       return ("You choose Car");
    }
    #endregion
}

và cả hai đều có Hợp đồng IChoice chỉ cần nói rằng Lớp của tôi nên có phương thức Mua

public interface IChoice
{
    string Buy();
}

Bây giờ, bạn thấy, giao diện đó chỉ thực thi phương thức Buy()nhưng để cho lớp kế thừa quyết định phải làm gì khi chúng thực hiện nó. Đây là hạn chế của Giao diện, sử dụng giao diện hoàn toàn, cuối cùng bạn có thể lặp lại một số tác vụ mà chúng ta có thể thực hiện tự động bằng cách sử dụng abstact. Trên ví dụ của chúng tôi, giả sử, mua mỗi chiếc xe có giảm giá.

public abstract class Choice
{
    public abstract string Discount { get; }
    public abstract string Type { get; }
    public string Buy()
    {
       return "You buy" + Type + " with " + Discount;
}
public class clsBike: Choice
{
    public abstract string Discount { get { return "10% Discount Off"; } }
    public abstract string Type { get { return "Bike"; } }
}

public class clsCar:Choice
{
    public abstract string Discount { get { return " $15K Less"; } }
    public abstract string Type { get { return "Car"; } }
}

Bây giờ bằng cách sử dụng Lớp Factory, bạn có thể đạt được điều tương tự nhưng khi sử dụng trừu tượng, bạn để lớp cơ sở thực thi Buy()phương thức.

Tóm tắt: Hợp đồng giao diện cho phép lớp kế thừa thực hiện trong khi Hợp đồng lớp trừu tượng có thể khởi tạo việc triển khai (có thể ghi đè bằng lớp Kế thừa)


2

Với một giao diện, bạn có thể làm như sau:

1) Tạo các giao diện tách biệt cung cấp các cách cắt khác nhau trong quá trình thực hiện của bạn, cho phép giao diện gắn kết hơn.

2) Cho phép nhiều phương thức có cùng tên giữa các giao diện, bởi vì, bạn không có triển khai xung đột, chỉ là một chữ ký.

3) Bạn có thể phiên bản và bỏ qua giao diện của mình một cách độc lập khi thực hiện, đảm bảo đáp ứng hợp đồng.

4) Mã của bạn có thể dựa vào sự trừu tượng hơn là sự lắng đọng, cho phép tiêm phụ thuộc thông minh, bao gồm cả tiêm thử Mocks, v.v.

Có nhiều lý do nữa tôi chắc chắn, đây chỉ là một vài lý do.

Một lớp trừu tượng cho phép bạn có một cơ sở cụ thể để làm việc, điều này không giống như một giao diện nhưng có những phẩm chất riêng của nó như khả năng tạo triển khai một phần bằng cách sử dụng mẫu phương thức mẫu.


Bạn đã bỏ qua điều quan trọng nhất: việc triển khai một giao diện làm cho lớp của bạn có thể sử dụng được bởi bất kỳ mã nào cần thực hiện giao diện đó, mà không có mã trong câu hỏi phải biết bất cứ điều gì về lớp của bạn.
supercat

2

Là một mẫu thực sự của câu trả lời @ user2211290:

Cả hai ArrayListcó giao diện IList. Dưới đây chúng tôi có một string[]và một List<string>và kiểm tra cả hai bằng một phương pháp bằng cách sử dụng IList :

string[] col1 = { "zero", "one", "two", "three", "four"};
List<string> col2 = new List<string>{ "zero", "one", "two", "three"};

//a methode that manipulates both of our collections with IList
static void CheckForDigit(IList collection, string digit)
{
    Console.Write(collection.Contains(digit));
    Console.Write("----");
    Console.WriteLine(collection.ToString()); //writes the type of collection
}

static void Main()
{
    CheckForDigit(col1, "one");   //True----System.String[]
    CheckForDigit(col2, "one");   //True----System.Collections.Generic.List`1[System.String]



//Another test:

    CheckForDigit(col1, "four");   //True----System.String[]
    CheckForDigit(col2, "four");   //false----System.Collections.Generic.List`1[System.String]
}

1

Bạn chỉ có thể kế thừa từ một lớp trừu tượng. Bạn có thể kế thừa từ nhiều giao diện. Điều này xác định những gì tôi sử dụng cho hầu hết các trường hợp.

Ưu điểm của lớp trừu tượng là bạn có thể có một triển khai cơ sở. Tuy nhiên, trong trường hợp IDis Dùng một lần, việc triển khai mặc định là vô ích, vì lớp cơ sở không biết cách dọn dẹp mọi thứ đúng cách. Do đó, một giao diện sẽ phù hợp hơn.


1

Cả lớp trừu tượng và giao diện là hợp đồng.

Ý tưởng của một hợp đồng là bạn chỉ định một số hành vi. Nếu bạn nói bạn đã thực hiện, bạn đã đồng ý với hợp đồng.

Sự lựa chọn của trừu tượng trên interrface là.

Bất kỳ hậu duệ không trừu tượng của lớp trừu tượng sẽ thực hiện hợp đồng.

đấu với

Bất kỳ lớp nào thực hiện giao diện sẽ thực hiện hợp đồng.

Vì vậy, bạn sử dụng trừu tượng khi bạn muốn chỉ định một số hành vi mà tất cả các hậu duệ phải thực hiện và tự lưu lại việc xác định một giao diện riêng, nhưng bây giờ mọi thứ đáp ứng hợp đồng tổng hợp hiệu quả này phải là một hậu duệ.


1

Các giao diện là để tạo ra một sự trừu tượng hóa (một nguyên mẫu) của sự trừu tượng hóa (các lớp) của thực tế (các đối tượng).

Các giao diện là để xác định các điều khoản hợp đồng mà không cung cấp triển khai được cung cấp bởi các lớp.

Các giao diện là thông số kỹ thuật:

  • Các giao diện là các tạo tác thời gian thiết kế để xác định hành vi bất động của khái niệm vì nó là một mình và tĩnh.

  • Các lớp là các tạo phẩm thời gian thực hiện để xác định cấu trúc di động của thực tế khi nó tương tác và di chuyển.

Giao diện là gì?

Khi bạn quan sát một con mèo, bạn có thể nói rằng đó là một con vật có bốn bàn chân, đầu, thân, đuôi và lông. Bạn có thể thấy rằng anh ta có thể đi bộ, chạy, ăn và meo. Và như thế.

Bạn vừa xác định một giao diện với các thuộc tính và hoạt động của nó. Như vậy, bạn chưa định nghĩa bất kỳ modus operandi nào, mà chỉ có các tính năng và khả năng mà không biết mọi thứ hoạt động như thế nào: bạn đã xác định các khả năng và sự khác biệt.

Vì vậy, nó thực sự chưa phải là một lớp mặc dù trong UML, chúng tôi gọi đây là một lớp trong sơ đồ lớp vì chúng tôi có thể định nghĩa các tư nhân và các thành viên được bảo vệ để bắt đầu có cái nhìn sâu sắc về tạo tác. Đừng nhầm lẫn ở đây vì trong UML, một giao diện hơi khác một chút so với giao diện trong C #: nó giống như một điểm truy cập một phần vào nguyên tử trừu tượng. Như vậy, chúng tôi đã nói rằng một lớp có thể thực hiện nhiều giao diện. Như vậy, đó là điều tương tự, nhưng không, bởi vì các giao diện trong C # đều được sử dụng để trừu tượng hóa sự trừu tượng hóa và để hạn chế sự trừu tượng hóa này như một điểm truy cập. Đó là hai cách sử dụng khác nhau. Do đó, một lớp trong UML đại diện cho một giao diện khớp nối đầy đủ với một lớp lập trình, trong khi đó một giao diện UML đại diện cho một giao diện tách rời của một phần của lớp lập trình. Thật, sơ đồ lớp trong UML không quan tâm đến việc triển khai và tất cả các tạo phẩm của nó đều ở cấp giao diện lập trình. Trong khi chúng ta ánh xạ các lớp UML thành các lớp lập trình, thì đó là sự chuyển đổi trừu tượng hóa thành trừu tượng hóa cụ thể. Có một sự tinh tế giải thích sự phân đôi giữa lĩnh vực thiết kế và lĩnh vực lập trình. Vì vậy, một lớp trong UML là một lớp lập trình theo quan điểm của giao diện lập trình trong khi xem xét những thứ ẩn bên trong.

Các giao diện cũng cho phép mô phỏng nhiều kế thừa khi không có sẵn một cách khó xử. Ví dụ, lớp mèo sẽ thực hiện giao diện mèo xuất phát từ giao diện động vật. Lớp mèo này cũng sẽ thực hiện các giao diện này: đi bộ, chạy, ăn và tạo ra âm thanh. Điều này bù đắp cho việc không có nhiều kế thừa ở cấp độ lớp, nhưng mỗi lần bạn cần thực hiện lại mọi thứ và bạn không thể tính đến thực tế tốt nhất như chính thực tế làm điều đó.

Để hiểu rằng chúng ta có thể tham khảo mã hóa Đối tượng Pascal nơi bạn xác định trong một đơn vị giao diện và các phần triển khai. Trong giao diện bạn xác định các loại và trong triển khai bạn thực hiện loại:

unit UnitName;

interface

type
  TheClass = class
  public
    procedure TheMethod;
  end;

implementation

class procedure TheClass.TheMethod;
begin
end;

Ở đây, phần giao diện khớp với thiết kế lớp UML trong khi các kiểu Giao diện là những thứ khác.

Vì vậy, trong kinh doanh của chúng tôi, chúng tôi có một từ, giao diện , để chỉ định hai điều khác biệt nhưng tương tự nhau, và đó là một nguồn gây nhầm lẫn.

Cũng trong C #, ví dụ, các giao diện lập trình cho phép bù đắp sự vắng mặt của đa hình chung thực sự trên các kiểu mở mà không thực sự thành công mục tiêu vì bạn đã mất khả năng đánh máy mạnh.

Xét cho cùng, các giao diện là cần thiết để cho phép các hệ thống không tương thích giao tiếp mà không phải lo lắng về việc triển khai và quản lý các đối tượng trong bộ nhớ như được giới thiệu với Mô hình Đối tượng chung (Phân tán).

Một lớp học là gì?

Sau khi xác định giảm thực tế theo quan điểm bên ngoài, bạn có thể mô tả nó từ góc nhìn bên trong: đây là lớp bạn xác định xử lý dữ liệu và quản lý thông báo để cho phép thực tế bạn được gói gọn để sống và cảm ơn cho các đối tượng sử dụng các thể hiện.

Vì vậy, trong UML, bạn nhận ra một sự nhúng chìm trong các bánh xe của máy móc và bạn mô tả các trạng thái, các tương tác và để có thể thực hiện sự trừu tượng của đoạn thực tế mà bạn muốn xử lý.

Như vậy, một lớp trừu tượng bằng cách nào đó tương đương với một giao diện theo quan điểm của trình biên dịch.

Thêm thông tin

Giao thức (lập trình hướng đối tượng)

C # - Giao diện

C # - Lớp học


1

Hãy để tôi nói với bạn về máy nướng bánh mì bay.

máy nướng bánh mì bay

Tất nhiên, có nhiều tình huống bạn có thể xây dựng một hệ thống phần mềm hoạt động mà không cần khai báo hay thực hiện bất kỳ giao diện nào: mọi thiết kế phần mềm hướng đối tượng đều có thể được thực hiện bằng cách sử dụng không có gì ngoài các lớp.

Sau đó, một lần nữa, bất kỳ hệ thống phần mềm nào cũng có thể được triển khai bằng Ngôn ngữ hội hoặc tốt hơn là bằng Mã máy. Lý do tại sao chúng ta sử dụng các cơ chế trừu tượng là bởi vì chúng có xu hướng làm cho mọi thứ dễ dàng hơn. Giao diện là một cơ chế trừu tượng như vậy.

Vì vậy, thực tế là có một số thiết kế hướng đối tượng không tầm thường, dễ thực hiện hơn nhiều nếu bạn sử dụng giao diện, giao diện đó thực tế trở nên cần thiết trong những trường hợp đó.

Các thiết kế không tầm thường này phải thực hiện với nhiều kế thừa, ở dạng "thật" của nó, là khi một lớp kế thừa không chỉ từ một lớp cơ sở, mà từ hai hoặc nhiều lớp cơ sở. Hình thức thực sự này không thể có trong C #, nhưng trước khi các ngôn ngữ như C # và Java ra đời, ngôn ngữ được cai trị là C ++, hỗ trợ đầy đủ tính kế thừa thực sự. Thật không may, nhiều kế thừa thực sự hóa ra không phải là một ý tưởng hay, bởi vì nó vô cùng phức tạp trong thiết kế ngôn ngữ, và nó cũng làm phát sinh nhiều vấn đề khác nhau, ví dụ như "Vấn đề kim cương" nổi tiếng. (Xem câu trả lời "Vấn đề chính xác với đa thừa kế là gì?" Của J Francis )

Vì vậy, nếu ai đó muốn xây dựng một lớp "máy nướng bánh mì bay", họ sẽ thừa hưởng từ một số loại "máy nướng bánh mì" hiện có và cũng từ một số loại "bay" hiện có. Vấn đề mà họ có thể gặp phải là nguồn cung cấp năng lượng của lớp máy nướng bánh mì có khả năng là ổ cắm trên tường, trong khi nguồn cung cấp năng lượng của lớp máy bay có thể là thức ăn của chim bồ câu, và lớp mới sẽ tạo ra bằng cách nào đó có cả hai, hoặc sẽ không rõ nó sẽ có cái nào. (Vấn đề kim cương.)

Những người tạo ra các ngôn ngữ như C # và Java đã quyết định không cho phép nhiều kế thừa thực sự, để giữ cho ngôn ngữ đơn giản và tránh những cạm bẫy như Vấn đề Kim cương. Tuy nhiên, một số hình thức thừa kế vẫn cần thiết, (hoặc ít nhất là rất mong muốn), vì vậy trong các ngôn ngữ này, họ đã giới thiệu các giao diện như một phương tiện hỗ trợ một hình thức thừa kế ít hơn trong khi tránh các vấn đề và sự phức tạp của đa kế thừa thực sự.

Trong hình thức đa thừa kế ít hơn này, bạn không được phép có một lớp kế thừa từ nhiều hơn một lớp cơ sở, nhưng ít nhất bạn có thể thừa kế từ một hoặc nhiều giao diện. Vì vậy, nếu bạn muốn xây dựng một máy nướng bánh mì bay, bạn không thể kế thừa cả từ một số máy nướng bánh mì hiện có và một số loại máy bay hiện có, nhưng những gì bạn có thể làm là kế thừa từ một máy nướng bánh mì hiện có và sau đó cũng hiển thị giao diện bay mà bạn tự thực hiện, có thể sử dụng bất cứ điều gì có nghĩa là bạn đã được thừa hưởng từ máy nướng bánh mì.

Vì vậy, trừ khi bạn cảm thấy cần phải tạo một lớp tổng hợp hai bộ chức năng khác nhau và không liên quan, bạn sẽ không cần bất kỳ hình thức thừa kế nào, vì vậy bạn sẽ không cần phải khai báo hoặc thực hiện bất kỳ giao diện nào.


0

Các giao diện cho phép người thiết kế lớp thực hiện các phương thức có sẵn rất rõ ràng cho người dùng cuối. Chúng cũng là một phần không thể thiếu của đa hình.


Vâng nói về tuyên bố đầu tiên của bạn. Nhưng tôi không hiểu câu nói thứ 2 của bạn, bạn có thể vui lòng giải thích với một ví dụ thời gian thực không?
Học viên

0

Tôi sẽ không đăng định nghĩa của một giao diện chống lại một lớp trừu tượng bởi vì tôi nghĩ rằng bạn biết rất rõ lý thuyết và tôi cho rằng bạn biết các nguyên tắc RẮN vì vậy hãy thực hành.

Như bạn đã biết các giao diện không thể có bất kỳ mã nào, vì vậy, phần mở rộng khá dễ hiểu.

nếu bạn cần khởi tạo thuộc tính của lớp cung cấp hàm tạo hoặc bạn muốn cung cấp một phần của việc triển khai, thì lớp trừu tượng sẽ phù hợp với giao diện không cho phép bạn làm điều đó.

Vì vậy, nói chung, bạn nên thích lớp trừu tượng hơn các giao diện khi bạn cần cung cấp hàm tạo hoặc bất kỳ mã nào cho máy khách sẽ kế thừa / mở rộng lớp của bạn


-2

Lớp trừu tượng được đặt trong các thực thể có liên quan trong đó Giao diện có thể được sử dụng cho các thực thể không liên quan.

Ví dụ: nếu tôi có hai thực thể nói Động vật và Con người thì tôi sẽ đi Giao diện, nếu như tôi phải đi chi tiết nói Tiger, sư tử và muốn liên hệ với Animal thì sẽ chọn lớp Tóm tắt động vật ..

sẽ trông như dưới đây

   Interface             
   ____|____
  |        |
Animal   Human



  Animal (Abstract class)
   __|___
  |      |
Tiger   Lion
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.