Menu
CoddyTech

Nhiều interface

Thuộc phần Lập trình hướng đối tượng trong hành trình C# của Coddy. Bài học 27 trên 70.

Một lớp chỉ có thể kế thừa từ một lớp cơ sở, nhưng có thể triển khai bao nhiêu giao diện tùy ý. Đây là một trong những ưu điểm chính của giao diện so với lớp trừu tượng, vì giao diện cho phép một lớp có nhiều hành vi.

Để triển khai nhiều giao diện, chỉ cần liệt kê chúng sau dấu hai chấm, cách nhau bằng dấu phẩy:

public interface IFlyable
{
    void Fly();
}

public interface ISwimmable
{
    void Swim();
}

public class Duck : IFlyable, ISwimmable
{
    public void Fly()
    {
        Console.WriteLine("Flying through the air");
    }
    
    public void Swim()
    {
        Console.WriteLine("Swimming in the pond");
    }
}

Lớp Duck phải triển khai tất cả thành viên từ cả hai giao diện. Cách này mô phỏng tự nhiên các tình huống thực tế: vịt thực sự có thể vừa bay vừa bơi, nên việc nó đáp ứng cả hai giao diện là hợp lý.

Khi kết hợp kế thừa với nhiều giao diện, lớp cơ sở phải đứng trước:

public class Duck : Bird, IFlyable, ISwimmable
{
    // Kế thừa từ Bird, triển khai cả hai giao diện
}

Sự linh hoạt này cho phép bạn kết hợp hành vi từ nhiều nguồn. Một Robot có thể triển khai IMovable, IChargeable và ISpeakable. Mỗi giao diện đại diện cho một khả năng riêng, và lớp của bạn có thể kết hợp chính xác những gì mình cần.

challenge icon

Thử thách

Dễ

Hãy xây dựng một hệ thống thiết bị nhà thông minh để minh họa cách một lớp có thể triển khai nhiều giao diện nhằm có thêm các khả năng khác nhau. Bạn sẽ tạo những thiết bị vừa có thể điều khiển, vừa có tính năng quản lý nguồn điện.

Bạn sẽ sắp xếp code trong bốn tệp:

  • IControllable.cs: Định nghĩa giao diện có tên IControllable trong không gian tên SmartHome. Giao diện này đại diện cho các thiết bị có thể bật và tắt. Giao diện khai báo hai phương thức: TurnOn() và TurnOff(), cả hai đều trả về một chuỗi.
  • INetworkConnected.cs: Định nghĩa giao diện có tên INetworkConnected trong không gian tên SmartHome. Giao diện này đại diện cho các thiết bị có thể kết nối với mạng. Giao diện khai báo phương thức Connect(string network), phương thức này trả về một chuỗi.
  • SmartTV.cs: Định nghĩa lớp SmartTV trong không gian tên SmartHome, lớp này triển khai cả IControllable và INetworkConnected. TV cần có thuộc tính Brand (chuỗi) và thuộc tính ScreenSize (số nguyên, biểu thị số inch). Tạo hàm khởi tạo nhận cả hai giá trị này. Triển khai tất cả phương thức của giao diện:
    • TurnOn() trả về "{Brand} {ScreenSize}-inch TV is now ON"
    • TurnOff() trả về "{Brand} {ScreenSize}-inch TV is now OFF"
    • Connect(string network) trả về "{Brand} TV connected to {network}"
  • Program.cs: Trong tệp chính, hãy tạo một đối tượng SmartTV bằng các giá trị đầu vào. Minh họa tính linh hoạt của nhiều giao diện bằng cách lưu cùng một đối tượng TV vào ba biến thuộc các kiểu khác nhau: kiểu cụ thể SmartTV, một biến IControllable và một biến INetworkConnected. Gọi các phương thức phù hợp thông qua từng tham chiếu để cho thấy cùng một đối tượng có thể được sử dụng theo những cách khác nhau, tùy vào giao diện bạn đang dùng.

Bạn sẽ nhận ba đầu vào:

  • Tên thương hiệu TV
  • Kích thước màn hình tính bằng inch
  • Tên mạng cần kết nối

In đầu ra theo định dạng này:

Via SmartTV:
{TurnOn() result}
{Connect(network) result}
Via IControllable:
{TurnOff() result}
Via INetworkConnected:
{Connect(network) result}

Ví dụ: nếu các đầu vào là Samsung, 55 và HomeWiFi, đầu ra sẽ là:

Via SmartTV:
Samsung 55-inch TV is now ON
Samsung TV connected to HomeWiFi
Via IControllable:
Samsung 55-inch TV is now OFF
Via INetworkConnected:
Samsung TV connected to HomeWiFi

Lưu ý cùng một đối tượng SmartTV có thể được truy cập thông qua các tham chiếu giao diện khác nhau. Khi lưu đối tượng dưới kiểu IControllable, bạn chỉ có thể gọi các phương thức điều khiển. Khi lưu đối tượng dưới kiểu INetworkConnected, bạn chỉ có thể gọi các phương thức mạng. Đây là sức mạnh của việc triển khai nhiều giao diện: một lớp có được nhiều khả năng mà vẫn linh hoạt trong cách sử dụng!

Tự làm thử

using System;
using SmartHome;

class Program
{
    public static void Main(string[] args)
    {
        // Đọc dữ liệu đầu vào
        string brand = Console.ReadLine();
        int screenSize = Convert.ToInt32(Console.ReadLine());
        string network = Console.ReadLine();
        
        // TODO: Tạo đối tượng SmartTV với các giá trị đầu vào
        
        // TODO: Lưu cùng một đối tượng TV vào ba biến có kiểu dữ liệu khác nhau:
        // 1. Kiểu SmartTV (lớp cụ thể)
        // 2. Kiểu IControllable (tham chiếu đến giao diện)
        // 3. Kiểu INetworkConnected (tham chiếu đến giao diện)
        
        // TODO: In đầu ra theo định dạng yêu cầu:
        // Via SmartTV:
        // - Gọi TurnOn() và Connect(network)
        // Via IControllable:
        // - Gọi TurnOff()
        // Via INetworkConnected:
        // - Gọi Connect(network)
        
    }
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch C# online