Các trường hợp sử dụng cho các giao diện của tư nhân


8

Tôi đã tự hỏi nếu có một trường hợp sử dụng hợp lệ để có thể xác định đúng các thuộc tính và chức năng nội bộ cụ thể của một lớp theo cách tương tự như cách một giao diện xác định các thuộc tính và chức năng chung của một lớp.

Hãy tưởng tượng nhiệm vụ mà bạn phải xây dựng một lớp mô tả một con người.

Rõ ràng, mỗi người là một sinh vật hình người nhưng không phải mọi sinh vật hình người đều là một con người, vì vậy bạn có thể có một giao diện IHumanoid với các chức năng như thế này (vì nó không hữu ích để mã hóa kế hoạch cơ thể vào lớp):

public interface IHumanoid {
    function get head():IHead;
    function get torso():ITorso;
    function get leftArm():IArm;
    function get rightArm():IArm;
    function get leftLeg():ILeg;
    function get rightLeg():ILeg;
}

Hơn nữa và rõ ràng, mỗi người là một động vật có vú nhưng không phải mọi động vật đều là một con người, vì vậy có lẽ có một giao diện khác là IMammal với hai định nghĩa cho nam và nữ trôi nổi ở đâu đó:

public interface IMammal {
    function procreate(partner:IMammal):void;
}

public interface IMaleMammal extends IMammal {
    function inseminate(female:IFemaleMammal):void;
}

public interface IFemaleMammal extends IMammal {
    function conceive(partner:IMaleMammal):Boolean;
    function giveBirth():IMammal;
    function nurse(offspring:IMammal):void;
}

Vì vậy, lớp của chúng ta bây giờ có thể trông giống như thế này:

public class Human implements IHumanoid, IMammal {
    private var _head:IHead;
    private var _torso:ITorso;
    private var _leftArm:IArm;
    private var _rightArm:IArm;
    private var _leftLeg:ILeg;
    private var _rightLeg:ILeg;

    public function Human() {
        // ctor...
    }

    public function get head():IHead {
        return _head;
    }

    public function get torso():ITorso {
        return _torso;
    }

    public function get leftArm():IArm {
        return _leftArm;
    }

    public function get rightArm():IArm {
        return _rightArm;
    }

    public function get leftLeg():ILeg {
        return _leftLeg;
    }

    public function get rightLeg():ILeg {
        return _rightLeg;
    }

    public function procreate(partner:IMammal):void {
        // "abstract" function
    }
}

public class MaleHuman extends Human implements IMaleMammal {
    override public function procreate(partner:IMammal):void {
        if (partner is IFemaleMammal) {
            inseminate(partner);
        }
    }

    public function inseminate(female:IFemaleMammal):void {
        female.conceive(this);
    }
}

public class FemaleHuman extends Human implements IFemaleMammal {
    override public function procreate(partner:IMammal):void {
        if (partner is IMaleMammal) {
            conceive(partner);
        }
    }

    public function conceive(partner:IMaleMammal):Boolean {
        // ...
    }

    public function giveBirth():IMammal {
        // ...
    }

    public function nurse(offspring:IMammal):void {
        // ...
    }
}

Từ đó, chúng ta có thể triển khai các lớp của mình hơn nữa và mọi thứ đều hoạt động tốt và ổn cho đến khi chúng ta có nhiệm vụ sử dụng các giao diện hiện có để thực hiện một số lớp khác. Có lẽ là một con khỉ đột, một con orca và một con thú mỏ vịt.

Bỏ qua vấn đề lớn, thú mỏ vịt sẽ đặt ra cấu trúc giao diện hiện tại của chúng tôi (* ho * trứng đặt động vật có vú * ho *), chúng tôi có "vấn đề" là không có gì ngăn cản chúng tôi cung cấp cho não khỉ đột 2, phổi 8 orca và nửa thú mỏ vịt một tá gan. Và mặc dù chúng tôi có thể bị xử lý kỷ luật đủ để tuân theo cấu trúc động vật có vú, nhưng chúng tôi không thể đảm bảo như vậy nếu chúng tôi mở API cho các nhà phát triển khác, những người có thể mã hóa một số thứ nghiêm trọng mà vẫn trông ổn với thế giới bên ngoài.

Do đó, tôi đã tự hỏi nếu có một trường hợp sử dụng hợp lệ để tạo ra một cái gì đó giống như "giao diện riêng" xác định các chức năng và thuộc tính không công khai. Có lẽ một cái gì đó dọc theo những dòng này:

public structure SMammal {
    function get brain():IBrain;
    function get liver():ILiver;
    function get leftLung():ILung;
    function get rightLung():ILung;
    function get leftKidney():IKidney;
    function get rightKidney():IKidney;
}

public class Human implements IHumanoid, IMammal follows SMammal {
    private function get brain():IBrain {
        // ...
    }

    private function get liver():ILiver {
        // ...
    }

    // etc. etc.
}

Liệu một tính năng như vậy tồn tại trong bất kỳ ngôn ngữ lập trình? Các lớp trừu tượng có thể được sử dụng để giải quyết điều này? Hoặc chúng ta không nên quan tâm đến điều này miễn là giao diện công cộng bằng cách nào đó hoạt động như mong đợi?


Các "IMumle" cách biểu thị một giao diện là một thói quen xấu, theo ý kiến của tôi

Hai bình luận. Thứ nhất, dường như chúng ta có thể dựa trên toàn bộ cuộc thảo luận về Lược đồ XML, thay vì các chi tiết cụ thể về giao diện ngôn ngữ. Thứ hai, "xác nhận" đôi khi (nhưng không phải luôn luôn) tách biệt tốt nhất với "cấu trúc".
rwong

Câu trả lời:


3

Và mặc dù chúng tôi có thể bị xử lý kỷ luật đủ để tuân theo cấu trúc động vật có vú, nhưng chúng tôi không thể đảm bảo như vậy nếu chúng tôi mở API cho các nhà phát triển khác, những người có thể mã hóa một số thứ nghiêm trọng mà vẫn trông ổn với thế giới bên ngoài.

Chính xác thì bạn đạt được gì khi buộc họ tuân theo cấu trúc của bạn? Bạn có thể phá vỡ một số cách sử dụng tiên tiến, có thể có một trường hợp cho một động vật có nhiều bộ não. Và lập trình viên máy khách có thể làm rối tung việc thực hiện một lớp theo nhiều cách điên rồ đến mức cố gắng ngăn chặn cảm giác này giống như cố gắng đóng cửa sổ trong một nỗ lực để giữ một con ngựa trong chuồng.

Đừng đối xử với các lập trình viên khách hàng của bạn như tù nhân. Nếu họ theo giao diện chung, hãy để mã chạy.


Tôi không muốn đối xử với những người sử dụng API như tù nhân, nhưng tôi đã suy nghĩ về điều gì đó dọc theo hướng dẫn cung cấp hướng dẫn về cách cấu trúc, ví dụ như một plugin cho khung hiện có. Giao diện plugin chỉ cho bạn biết tiện ích mở rộng của bạn sẽ được khung sử dụng như thế nào, nhưng nó không cho bạn biết gì về cách các plugin được cho là hoạt động nội bộ.

Bạn có quan điểm về các cách sử dụng nâng cao không được áp dụng theo một số phương pháp cắt cookie, nhưng bạn cũng có thể dễ dàng chạy vào những ứng dụng có giao diện chung (ví dụ: trong C # bạn cần / muốn trả lại IList<T>nhưng giao diện yêu cầu bạn phải trả lại an IEnumerable<T>). Và cuối cùng nhưng không kém phần quan trọng, không có loài động vật nào được biết đến với nhiều bộ não (dư thừa, giống như tất cả các cơ quan trùng lặp của chúng ta). Vì vậy, trong khi có thể có trường hợp như thế này (ví dụ như nhện), nó gần như chắc chắn sẽ không phải là động vật có vú, vì vậy dù sao nó cũng sẽ là một giao diện / cấu trúc hoàn toàn khác.

@arotter, tôi là tất cả để cung cấp hướng dẫn về cách tốt nhất để cấu trúc nội bộ mọi thứ. Nhưng tôi không thấy bất kỳ lý do nào để yêu cầu một cấu trúc nội bộ cụ thể. Toàn bộ điểm của giao diện là xác định giao diện chung chứ không phải thực hiện.
Winston Ewert

1

Vì một loại giao diện theo mặc định là một thành viên công cộng, mọi thứ trong đó sẽ được công khai nhưng tôi đã thấy điều này:

/programming/792908/what-is-a-private-interface

từ msd:

Các giao diện bao gồm các phương thức, thuộc tính, sự kiện, bộ chỉ mục hoặc bất kỳ sự kết hợp nào của bốn loại thành viên đó. Một giao diện không thể chứa các hằng, trường, toán tử, hàm tạo cá thể, hàm hủy hoặc loại. Nó không thể chứa các thành viên tĩnh. Các thành viên giao diện được tự động công khai và họ không thể bao gồm bất kỳ công cụ sửa đổi truy cập nào.

http://msdn.microsoft.com/en-us/l Library / ms173156.aspx


Có, các thành viên của một giao diện là công khai. Điều đó không có nghĩa là bạn không thể có một thành viên riêng của một số loại giao diện mà bạn không để lộ trong giao diện của riêng mình. Thực hiện một giao diện là công khai. Sử dụng một giao diện có thể là riêng tư như bạn muốn. OP về cơ bản là hỏi làm thế nào anh ta có thể khai báo một lớp để sử dụng các giao diện cụ thể một cách riêng tư, do đó đảm bảo rằng bất kỳ lớp thực hiện nào thực sự thực hiện các phương thức đó.
Marjan Venema

Có, tôi đồng ý với bạn do đó tại sao tôi đăng một liên kết hiển thị giao diện với các thành viên riêng.
Ali Jafer

À, được rồi Cũng ẩn ... :)
Marjan Venema

Câu hỏi không phải là về các giao diện trong C # (hoặc trong bất kỳ ngôn ngữ hiện có nào khác) mà là về khái niệm cơ bản. Bài viết này không đề cập đến nó cả.
Peter Taylor

0

Liệu một tính năng như vậy tồn tại trong bất kỳ ngôn ngữ lập trình? Các lớp trừu tượng có thể được sử dụng để giải quyết điều này? Hoặc chúng ta không nên quan tâm đến điều này miễn là giao diện công cộng bằng cách nào đó hoạt động như mong đợi?

Nó chắc chắn làm. Khá nhiều tính năng tồn tại trong một số ngôn ngữ.

Ví dụ, trong Objective-C ++ (lập trình iOS / Mac), quy trình chuẩn cho một lớp có ít nhất hai giao diện. Trên đó là công khai, và một là riêng tư. Đôi khi, họ cũng sẽ có các giao diện bổ sung được xác định ở nơi khác (ví dụ: lớp chuỗi cấp thấp có giao diện để thực hiện các hoạt động vẽ màn hình GUI trên chuỗi, được xác định trong một khung / thư viện hoàn toàn tách biệt với giao diện xác định chuỗi lớp học).

Về cơ bản cách tôi đối xử công khai / riêng tư rất đơn giản:

Các yếu tố giao diện công cộng không bao giờ có thể thay đổi. Bất cứ khi nào bạn cấu trúc lại hoặc cải thiện mã của mình, giao diện công cộng vẫn cần phải hoạt động chính xác như trước.

Mặt khác, các giao diện riêng tư có thể được thay đổi hoặc loại bỏ hoàn toàn bất cứ khi nào bạn muốn. Miễn là bạn cập nhật tất cả mã trong lớp để hiểu hành vi mới, bạn sẽ ổn. Thông thường giao diện công cộng sẽ có đầy đủ một hoặc hai phương thức dòng bàn giao công việc thực tế cho giao diện riêng.

Objective-C ++ cũng có khái niệm "được bảo vệ" trong giao diện, trong đó một cái gì đó có sẵn cho các lớp con nhưng không phải là các lớp bên ngoài.

Thông thường mã của tôi được phân chia khoảng một nửa và một nửa giữa công khai và riêng tư. Tôi không sử dụng được bảo vệ nhiều, mặc dù nó rất hữu ích một lần.


0

Ít nhất là trong các ngôn ngữ .NET, có thể áp dụng một công cụ xác định truy cập vào một giao diện. Điều này có thể hữu ích khi một số kết hợp của các lớp bên trong của một hội đồng chia sẻ các khả năng chung, nhưng các kết hợp và khả năng đó không phù hợp với mối quan hệ phân cấp. Thực tế là các khả năng không phù hợp với mối quan hệ phân cấp khiến cho việc sử dụng các giao diện để thể hiện chúng là cần thiết, nhưng không có nghĩa là mã bên ngoài nên được phép xác định các loại yêu cầu thực hiện giao diện. Hơn nữa, các giao diện không thể chứa bất kỳ phương thức nào có kiểu tham số hoặc kiểu trả về có quyền truy cập hẹp hơn so với chính các giao diện. Nếu lớp Fredđược khai báo internalvà một giao diện IFredcó một phương thức trả về a Fred, thì giao diện phải được khai báointernal . Nếu lớp lồng nhau Fred.Joeprivatevà giao diện lồng nhau Fred.IJoecó một phương pháp mà trả về một Fred.Joe, sau đó Fred.IJoephải tương tự như vậy được công bốprivate.

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.