Tại sao các giao diện yêu cầu các phương thức trên các thành viên?


8

... Vì điều này buộc chúng ta phải tạo ra getters và setters, trong thực tế thường hoàn toàn không liên quan? Có bất kỳ lý do thiết kế ngôn ngữ tốt nào tại sao các giao diện trong hầu hết các ngôn ngữ (tất cả?) Không cho phép các trường thành viên giúp hoàn thành thông số kỹ thuật giao diện không?

Trong hầu hết các ngôn ngữ còn tồn tại, các thành viên được đối xử cơ bản khác với các phương pháp, nhưng điều này CÓ phải là trường hợp không? Trong ngôn ngữ lý thuyết, chúng ta không thể có giao diện (a) chỉ định phương thức zero-args là getter, nhưng chấp nhận một thành viên có thể đọc được như người triển khai và (b) đã chỉ định phương thức một đối số là setter, nhưng được chấp nhận một trường thành viên có thể ghi là người triển khai của nó, đưa ra một ngôn ngữ hỗ trợ chỉ định kiểm soát truy cập trực tiếp vào các biến khi chúng được khai báo? Một ngôn ngữ nguyên mẫu cho phép nhiều kế thừa (để giải quyết điểm rất hợp lệ mà một số người trả lời đã thực hiện), sẽ là lý tưởng cho một cái gì đó như thế này.

Xin vui lòng thông báo cho tôi nếu một cái gì đó như thế này đã tồn tại.


2
Uh ... phương pháp thành viên. Tôi đoán bạn có nghĩa là "lĩnh vực thành viên"?
Aaronaught

OK để sử dụng thuật ngữ Java thích hợp, vâng, "các trường thành viên". Cảm ơn đã chỉ ra rằng.
Kỹ sư

1
OOP hút, nhưng hãy thử C # nếu bạn phải.
Công việc

Câu trả lời:


3

Rõ ràng trong hầu hết các ngôn ngữ còn tồn tại, các thành viên được đối xử cơ bản khác với các phương pháp, nhưng điều này CÓ phải là trường hợp không?

Không cho bất kỳ lý do căn cứ lý thuyết. Tôi nghĩ rằng những lý do bạn không thấy nó thường là thực tế:

Đầu tiên là cách bạn đối phó với những điều này trong thời gian chạy. Trong Java hoặc C ++, việc gán cho một thành viên công khai nguyên thủy như thế foo.x = 5này rất dễ xử lý: nhét 5vào một số thanh ghi, tìm ra nơi trong bộ nhớ của xthành viên foosống và bỏ đăng ký ở đó. Trong một ngôn ngữ như C # nơi các lớp có thể gói gọn các bài tập chặn cho các thành viên hoặc tính toán trước cách các thành viên đó sẽ đánh giá , trình biên dịch sẽ không có tiên nghiệmkiến thức về việc triển khai một lớp có sẵn trong thời gian chạy có sử dụng tính năng đó không. Điều đó có nghĩa là tất cả các bài tập và đánh giá của các thành viên công cộng phải được hoãn lại để thực hiện. * Các hoạt động liên quan đến nhiều quyền truy cập vào các thành viên đó đã thực hiện một cú đánh hiệu suất vì họ liên tục thực hiện các cuộc gọi chương trình con có thể được xử lý nhanh hơn thường xuyên bài tập nội tuyến. Việc tách đánh giá và phân công tách biệt khỏi getters và setters cung cấp cho nhà phát triển một số quyền kiểm soát đối với cách họ xử lý trong một tình huống nhất định.

Thứ hai là tuổi tác. Ngoại trừ có thể có F #, không có ngôn ngữ nào được sử dụng rộng rãi ngày nay là trẻ hơn một thập kỷ và ngay cả khi gần đây, các chu kỳ bổ sung cần thiết để đánh giá và chuyển nhượng bị chặn có thể không được chấp nhận.

Thứ ba là quán tính. Tôi nghĩ ở một mức độ nào đó, vẫn còn một số kỳ thị liên quan đến việc giao trực tiếp cho các thành viên công cộng ngay cả khi ngôn ngữ không cho phép lớp học thao túng họ và mọi người vẫn nghĩ về mặt getters và setters là tốt hơn. Điều đó sẽ mất dần theo thời gian, giống như đã làm với tất cả những người có mũi trong không khí so với những người viết chương trình bằng ngôn ngữ cấp cao hơn thay vì lắp ráp.


* Có một sự đánh đổi đi kèm với điều này: một ngôn ngữ phải đi cả tiếng với việc trì hoãn các bài tập / bài tập cho lớp hoặc chùn bước trong thời gian chạy nếu mã sử dụng các bài tập / bài tập nội tuyến cho một lớp nhất định cố gắng liên kết với một triển khai ngăn chặn chúng . Cá nhân, tôi nghĩ rằng cái sau là một ý tưởng tồi bởi vì nó buộc phải biên dịch lại mã sử dụng API không thay đổi.


Cảm ơn bạn, bạn đã hiểu được lực đẩy của câu hỏi của tôi và nhận được các chi tiết nghiệt ngã của TẠI SAO. Tôi có linh cảm rằng tốc độ sẽ là một trong những lý do - như mọi khi bạn đi vào con đường "năng động hơn". Như chúng ta đang thấy hiện nay với các ngôn ngữ như JS và Python, tính linh hoạt thường vượt qua tốc độ, do đó, "quán tính" mà bạn đề cập đến các xu hướng thiết kế ngôn ngữ nhất định dựa trên tối ưu hóa (những gì đã từng cần thiết) dần tan biến.
Kỹ sư

F # chủ yếu dựa trên CAML khách quan - nó có thể trẻ hơn một thập kỷ, nhưng hầu hết (có thể là tất cả) các ý tưởng đều cũ hơn.
Steve314

1
Tôi hơi tò mò tại sao hai downvoters nhấn nút màu đỏ.
Blrfl

@Blrfl: Quan điểm phê bình của tôi sẽ là câu trả lời của bạn tập trung quá nhiều vào chi tiết triển khai, thay vì nhìn nó từ quan điểm thiết kế ngôn ngữ. Tôi đã không đánh giá thấp bạn cho nó mặc dù, nhưng có lẽ những người khác có.
Niels van der Nghỉ

Scala cũng tương đối trẻ và được sử dụng rộng rãi
Tên hiển thị

10

Trong hầu hết các ngôn ngữ còn tồn tại, các thành viên [trường?] Được đối xử cơ bản khác với các phương thức, nhưng điều này CÓ phải là trường hợp không?

Vâng, nó làm.

Các trường thành viên là dữ liệu theo trường hợp. Dữ liệu phải thực sự tồn tại ở đâu đó trong bộ nhớ cho mọi trường hợp - phải có một địa chỉ hoặc chuỗi địa chỉ dành riêng cho nó. Trong Java, .NET và nhiều ngôn ngữ OO khác, dữ liệu này đi vào heap.

Phương thức là dữ liệu trên mỗi lớp. Họ là con trỏ đến một vtable. Đó là cách các phương thức có được công văn ảo. Thực tế chỉ có một trường hợp được phân bổ, mỗi lớp.

Một giao diện về cơ bản là một loại lớp đặc biệt chỉ chứa các phương thức, không có dữ liệu cá thể. Đó là một phần của định nghĩa về giao diện. Nếu nó chứa bất kỳ dữ liệu nào, nó sẽ không còn là một giao diện nữa, nó sẽ là một lớp trừu tượng. Tất cả các lựa chọn đó đều tốt, tất nhiên, tùy thuộc vào loại mẫu thiết kế bạn đang cố gắng thực hiện. Nhưng nếu bạn đã thêm dữ liệu cá thể vào giao diện, bạn sẽ lấy đi mọi thứ tạo nên giao diện.

OK, vậy tại sao một phương thức giao diện không thể trỏ đến một trường thành viên? Bởi vì không có gì ở cấp lớp để chỉ đến. Một lần nữa, một giao diện không có gì ngoài một bảng phương thức. Trình biên dịch chỉ có thể tạo một bảng và mọi phương thức trong nó phải trỏ đến cùng một địa chỉ bộ nhớ. Do đó, các phương thức giao diện không thể trỏ đến các trường lớp, vì trường lớp là một địa chỉ khác nhau cho mọi trường hợp.

Có lẽ trình biên dịch có thể chấp nhận điều này bằng mọi cách và tạo ra một phương thức getter để giao diện trỏ tới - nhưng về cơ bản nó trở thành một thuộc tính . Nếu bạn muốn biết tại sao Java không có các thuộc tính, thì ... đó là một câu chuyện thực sự dài và tẻ nhạt mà tôi không muốn vào đây. Nhưng nếu bạn quan tâm, bạn có thể muốn có một cái nhìn tại ngôn ngữ OO khác mà làm thực hiện các thuộc tính, chẳng hạn như C # hoặc Delphi. Cú pháp rất dễ:

public interface IFoo
{
    int Bar { get; }
}

public class Foo : IFoo
{
    public int Bar { get; set; }
}

Đúng, đó là tất cả để có nó. Quan trọng: Đây không phải là các trường, "int Bar" trong Foolớp là Thuộc tính tự động và trình biên dịch đang thực hiện chính xác những gì tôi vừa mô tả ở trên: tự động tạo getters và setters (cũng như trường thành viên sao lưu).

Vì vậy, để tóm tắt câu trả lời cho câu hỏi của bạn:

  • Các giao diện yêu cầu các phương thức vì toàn bộ mục đích của chúng không chứa bất kỳ dữ liệu nào;
  • Lý do không có đường cú pháp để giúp lớp thực hiện giao diện dễ dàng hơn chỉ đơn giản là các nhà thiết kế Java sẽ không làm điều đó - và đến thời điểm này, khả năng tương thích ngược là một vấn đề. Các nhà thiết kế ngôn ngữ thực hiện các loại lựa chọn này; bạn sẽ chỉ phải đối phó với nó, hoặc chuyển đổi.

Đây là một câu trả lời tốt, đặc biệt tôi tìm thấy thông tin về chức năng tra cứu thông tin. Cảm ơn.
Kỹ sư

9

đây là kết quả của việc ẩn thông tin, tức là những thành viên đó không nên hiển thị dưới dạng các trường mà là các thuộc tính có thể hoặc không thể được lưu trữ / lưu trữ cục bộ

một ví dụ là mã băm nó thay đổi khi đối tượng thay đổi, vì vậy tốt hơn là tính toán nó khi được yêu cầu và không phải mỗi khi đối tượng thay đổi

bên cạnh đó, hầu hết các ngôn ngữ là thừa kế đơn + đa thực hiện và cho phép các trường là một phần của giao diện đưa bạn vào lãnh thổ đa thừa kế (điều duy nhất còn thiếu là triển khai các chức năng mặc định) là trường hợp của các trường hợp cạnh phải


lĩnh vực đa thực hiện là vấn đề ở đây.
DeadMG

Tôi phải nói rằng, nghĩ về điều này hơn nữa, tôi không thực sự đồng ý về việc thừa kế nhiều lần. Bởi vì điều tôi thực sự hỏi là liệu việc thể hiện các thành viên dữ liệu trong các giao diện có khả thi hay không, liệu bạn có thể sử dụng các thành viên dữ liệu để xây dựng các giao diện hay không (về cơ bản là một lớp trừu tượng C ++). Có một sự khác biệt quan trọng ở đó.
Kỹ sư

Thực sự không có vấn đề gì với MI; một ngôn ngữ sẽ phải chùn bước khi thực hiện hai giao diện với các loại xung đột cho cùng một thành viên.
Blrfl

6

Các biến thành viên là việc thực hiện của lớp, không phải giao diện. Bạn có thể muốn thay đổi việc triển khai, vì vậy các lớp khác không được phép tham khảo trực tiếp việc triển khai đó.

Hãy xem xét một lớp với các phương thức sau - cú pháp C ++, nhưng điều đó không quan trọng ...

class example
{
  public:
    virtual void Set_Mode (int p_mode);
    virtual int  Mode () const;
};

Có vẻ như khá rõ ràng rằng sẽ có một biến thành viên được gọi modehoặc m_modetương tự lưu trữ trực tiếp giá trị chế độ đó, thực hiện khá nhiều thứ mà "tài sản" sẽ làm trong một số ngôn ngữ - nhưng điều đó không hẳn đúng. Có rất nhiều cách khác nhau để điều này có thể được xử lý. Ví dụ: phương thức Set_Mode có thể ...

  1. Xác định chế độ bằng cách sử dụng câu lệnh chuyển đổi.
  2. Khởi tạo một lớp con của một số lớp bên trong, tùy thuộc vào giá trị chế độ đó.
  3. Lưu trữ một con trỏ đến thể hiện đó như một biến thành viên.

Khi đã thực hiện điều đó, nhiều phương thức khác của lớp mẫu có thể gọi các phương thức thích hợp của lớp bên trong đó thông qua con trỏ, nhận hành vi cụ thể theo chế độ mà không cần kiểm tra chế độ hiện tại là gì.

Vấn đề ở đây là ít có một cách khả thi để thực hiện loại điều này, và nhiều hơn nữa vào một lúc nào đó bạn có thể thay đổi suy nghĩ của mình. Có thể bạn đã bắt đầu với một biến đơn giản, nhưng tất cả các câu lệnh chuyển đổi để xác định chế độ trong mọi phương thức đều bị đau. Hoặc có thể bạn đã bắt đầu với điều con trỏ dụ, nhưng điều đó hóa ra quá nặng nề cho tình huống của bạn.

Nó chỉ ra rằng những điều như thế này có thể xảy ra cho bất kỳ dữ liệu thành viên. Bạn có thể cần phải thay đổi đơn vị mà một giá trị được lưu trữ trong từ dặm sang km, hoặc bạn có thể thấy rằng bạn enumerate độc ​​đáo-xác định-the-trường hợp không còn duy nhất có thể xác định tất cả các trường hợp mà không xem xét một số thông tin thêm, hoặc bất cứ điều gì.

Điều này cũng có thể xảy ra đối với các phương thức - một số phương pháp hoàn toàn dành cho sử dụng nội bộ, phụ thuộc vào việc triển khai và nên ở chế độ riêng tư. Nhưng nhiều phương thức là một phần của giao diện và sẽ không cần phải đổi tên hoặc bất cứ điều gì chỉ vì việc triển khai nội bộ của lớp đã được thay thế.

Dù sao, nếu việc triển khai của bạn bị lộ, chắc chắn các mã khác sẽ bắt đầu phụ thuộc vào nó và bạn sẽ bị khóa để giữ việc thực hiện đó. Nếu việc triển khai của bạn bị ẩn khỏi mã khác, tình huống đó không thể xảy ra.

Chặn truy cập vào chi tiết thực hiện được gọi là "ẩn dữ liệu".


"Mã cho một giao diện, không phải là một triển khai" ... Phải. Đôi khi chúng ta biết những điều này gần đây nhưng phải có ai đó giải thích chúng như bạn đã làm, để thực sự củng cố các khái niệm một lần nữa.
Kỹ sư

OK chờ một phút. Sau khi suy nghĩ thêm, xin vui lòng xem chỉnh sửa của tôi cho câu hỏi.
Kỹ sư

Có một chút khó khăn để tìm ra chỉnh sửa của bạn là gì - vì một số lý do, khác với một số chỉnh sửa cũ hơn không được hiển thị. Tuy nhiên, điều tôi nghĩ rằng câu nói của bạn là "tại sao tài sản không thể có biến thành viên làm triển khai mặc định?" Một thuộc tính trông (giao diện) giống như một biến thành viên, nhưng được thực hiện thông qua các phương thức getter / setter. Và IMO không có lý do tại sao, theo mặc định, các phương thức getter / setter đó không nên thực hiện đọc / ghi vào biến thành viên - hoặc tại sao cuộc gọi getter và setter không được tối ưu hóa khi an toàn - cho phép kế thừa, tách biệt tổng hợp, v.v.
Steve314

@Nick - Vì vậy, vâng, miễn là có thể nói "getter và / hoặc setter cho thuộc tính này là thuần túy" hoặc " không nên là mặc định" Tôi nghĩ đó là một ý tưởng tốt - loại bỏ một số lộn xộn cho một trường hợp phổ biến với các thuộc tính. Tôi không biết liệu đã có ngôn ngữ nào chưa - chưa sử dụng các thuộc tính ngay cả trong các ngôn ngữ nơi chúng tồn tại - nhưng tôi rất ngạc nhiên nếu ngôn ngữ này chưa được hỗ trợ.
Steve314

3

Như những người khác đã lưu ý, một giao diện mô tả những gì một lớp làm, không phải nó làm như thế nào . Đó thực chất là một hợp đồng kế thừa các lớp phải tuân thủ.

Những gì bạn mô tả hơi khác một chút - một lớp cung cấp một số thực hiện nhưng có lẽ không phải tất cả, như một hình thức tái sử dụng. Chúng thường được gọi là các lớp trừu tượng và được hỗ trợ trong một số ngôn ngữ (ví dụ: C ++ và Java). Các lớp này không thể được khởi tạo theo quyền riêng của chúng, chúng chỉ có thể được kế thừa bởi các lớp cụ thể (hoặc trừu tượng hơn).

Một lần nữa như đã lưu ý, các lớp trừu tượng có xu hướng có giá trị nhất trong các ngôn ngữ hỗ trợ đa kế thừa vì chúng có thể được sử dụng để cung cấp các phần chức năng bổ sung cho một lớp lớn hơn. Điều này thường được coi là phong cách xấu, tuy nhiên, vì nói chung một mối quan hệ tổng hợp ("có-a") sẽ phù hợp hơn


Câu trả lời tốt. Tôi có xu hướng ủng hộ sáng tác gần như hoàn toàn trong các loại nhiệm vụ tôi đảm nhận những ngày này. Cá nhân tôi không tin vào cách xử lý riêng biệt các lớp và giao diện trừu tượng trong một số ngôn ngữ nhất định, như những người khác trong diễn đàn này đã nêu, mặc dù có những lý do cho điều này, nói chung những lý do này là do những hạn chế ngôn ngữ cơ bản (như được đề cập trong bình luận của tôi trên câu trả lời của ratchet freak).
Kỹ sư

1
Tôi có xu hướng đồng ý với nhận xét của bạn re: trừu tượng / giao diện. Khi tôi nhìn lại mã cũ nơi tôi đã sử dụng rất nhiều lớp trừu tượng, tôi thấy rõ hơn với kinh nghiệm của mình sau 10 - 15 năm rằng tôi đã sử dụng các tính năng ngôn ngữ để viết mã xung quanh thiết kế xấu
Steve Mallam

1

Xin vui lòng thông báo cho tôi nếu một cái gì đó như thế này đã tồn tại.

Các thuộc tính Objective-C cung cấp loại chức năng này với các bộ truy cập thuộc tính tổng hợp của nó. Một thuộc tính Objective-C về cơ bản chỉ là một lời hứa mà một lớp cung cấp các hàm truy cập, điển hình là dạng foocho getter và setFoo:cho setter. Khai báo thuộc tính chỉ định các thuộc tính nhất định của các bộ truy cập liên quan đến quản lý bộ nhớ và các hành vi luồng. Ngoài ra còn có một lệnh @synthesizechỉ thị cho trình biên dịch tạo ra các bộ truy cập và thậm chí cả biến thể hiện tương ứng, vì vậy bạn không phải bận tâm đến việc viết getters và setters hoặc khai báo một ivar cho mỗi thuộc tính. Ngoài ra còn có một số đường cú pháp làm cho truy cập thuộc tính trông giống như truy cập vào các trường của một cấu trúc, nhưng thực sự dẫn đến việc gọi các trình truy cập thuộc tính.

Kết quả của tất cả những điều đó là tôi có thể khai báo một lớp với các thuộc tính:

@interface MyClass : NSObject
{}
@property (assign) int foo;
@property (copy) NSString *bar;
@end

và sau đó tôi có thể viết mã trông giống như nó truy cập trực tiếp vào ivars, nhưng thực tế sử dụng các phương thức accessor:

MyClass *myObject = [[MyClass alloc] init];  // create myObject

// setters
myObject.foo = 127;                 // same as [myObject setFoo:127];
myObject.bar = @"Hello, world!";    // same as [myObject setBar:@"Hello, world!"];

// getters
int i = myObject.foo                // same as [myObject foo];
NSString *s = myObject.bar          // same as [myObject bar];

Người ta đã nói rằng các trình truy cập cho phép bạn tách giao diện khỏi triển khai và lý do bạn muốn làm điều đó là để duy trì khả năng thay đổi triển khai trong tương lai mà không ảnh hưởng đến mã máy khách. Hạn chế là bạn phải đủ kỷ luật để viết và sử dụng người truy cập chỉ để giữ cho các tùy chọn trong tương lai của bạn mở. Objective-C làm cho việc tạo và sử dụng các bộ truy cập dễ dàng như sử dụng ngà trực tiếp. Trên thực tế, vì họ đảm nhiệm phần lớn công việc quản lý bộ nhớ, nên việc sử dụng các thuộc tính thực sự dễ dàng hơn rất nhiều so với việc truy cập trực tiếp vào ivars. Và khi đến lúc bạn muốn thay đổi việc triển khai, bạn luôn có thể cung cấp trình truy cập của riêng bạn thay vì để trình biên dịch tạo chúng cho bạn.


1

Tại sao các giao diện yêu cầu các phương thức trên các thành viên?

... Vì điều này buộc chúng ta phải tạo ra getters và setters, trong thực tế thường hoàn toàn không liên quan? Có bất kỳ lý do thiết kế ngôn ngữ tốt nào tại sao giao diện trong hầu hết các ngôn ngữ (tất cả?) Không cho phép các thành viên giúp hoàn thành thông số kỹ thuật giao diện không?

"Hầu hết" ngôn ngữ? Những ngôn ngữ bạn đã điều tra? Trong các ngôn ngữ động không có giao diện. Chỉ có ba hoặc bốn ngôn ngữ OO được nhập tĩnh với bất kỳ mức độ phổ biến nào: Java, C #, Objective-C và C ++. C ++ không có giao diện; thay vào đó chúng tôi sử dụng các lớp trừu tượng và một lớp trừu tượng có thể chứa một thành viên dữ liệu công khai. Cả C # và Objective-C đều hỗ trợ các thuộc tính, do đó không cần getters và setters trong các ngôn ngữ đó. Chỉ còn lại Java. Có lẽ lý do duy nhất mà Java không hỗ trợ các thuộc tính là rất khó để giới thiệu chúng theo kiểu tương thích ngược.


Các thành viên có nghĩa là đề cập đến "các trường thành viên" trái ngược với "các hàm thành viên" mà tôi gọi đơn giản là các phương thức. Tôi không chắc từ ngôn ngữ nào (nếu có) tôi đã chọn quy ước này. Vì vậy, với những gì tôi đã viết, tôi thấy câu trả lời của bạn, nhưng tôi đoán một nhận xét dưới câu hỏi của tôi để làm rõ sẽ có tính xây dựng hơn.
Kỹ sư

Re C ++, touché. Tuy nhiên, thực sự có các giao diện trong các ngôn ngữ động, JS và Python là hai giao diện ngay lập tức nảy ra trong đầu. Liệu một người đề xuất các ngôn ngữ gõ tĩnh có gọi các "giao diện" này hay không, là một cuộc thảo luận khác mà tôi thấy không có điểm nào để tham gia. Cá nhân tôi thể hiện ít ưu tiên cho cả hai bên của hàng rào đó, sử dụng khi tôi thực hiện một loạt các ngôn ngữ cho các mục đích khác nhau.
Kỹ sư

@Nick: JS và Python có sự kế thừa, nhưng tôi không nói là chúng có giao diện; người ta có thể gọi bất kỳ phương thức nào trên bất kỳ đối tượng nào.
kevin cline

1

Một số câu trả lời đề cập đến 'ẩn thông tin' và 'chi tiết triển khai' vì các phương thức giao diện lý do được ưa thích hơn các trường. Tôi nghĩ lý do chính đơn giản hơn thế.

Các giao diện là một tính năng ngôn ngữ cho phép bạn trao đổi hành vi bằng cách có nhiều lớp thực hiện một giao diện. Hành vi của một lớp được định nghĩa bởi các phương thức của nó. Các trường, mặt khác, chỉ phản ánh trạng thái của một đối tượng.

Tất nhiên, các trường hoặc thuộc tính của một lớp có thể là một phần của hành vi, nhưng chúng không phải là phần quan trọng của hợp đồng được xác định bởi giao diện; chúng chỉ là kết quả Đó là lý do tại sao ví dụ C # cho phép bạn xác định các thuộc tính trong một giao diện và trong Java, bạn xác định một getter trong giao diện. Đây là nơi một chút ẩn thông tin phát huy tác dụng, nhưng nó không phải là điểm chính.

Như tôi đã nói trước đây, các giao diện cho phép bạn trao đổi hành vi, nhưng hãy xem phần trao đổi. Một giao diện cho phép bạn thay đổi triển khai cơ bản bằng cách tạo một lớp triển khai mới. Vì vậy, có một giao diện bao gồm các trường không có nhiều ý nghĩa, bởi vì bạn không thể thay đổi nhiều về việc triển khai các trường.

Lý do duy nhất bạn muốn tạo giao diện chỉ có trường là khi bạn muốn nói rằng một số lớp là một loại đối tượng nhất định. Tôi đã nhấn mạnh phần 'là một phần', vì bạn nên sử dụng tính kế thừa thay vì giao diện.


Lưu ý bên lề: Tôi biết rằng thành phần mà nó ưa thích hơn sự kế thừa và thành phần thường chỉ có thể đạt được bằng cách sử dụng các giao diện, nhưng sử dụng các giao diện chỉ để 'gắn thẻ' một lớp với một số thuộc tính cũng tệ như vậy. Kế thừa là tuyệt vời khi được sử dụng một cách thích hợp và miễn là bạn tuân thủ Nguyên tắc Trách nhiệm duy nhất, bạn không nên có bất kỳ vấn đề nào.

Ý tôi là, tôi chưa bao giờ làm việc với thư viện điều khiển UI chẳng hạn, không sử dụng tính kế thừa. Khu vực duy nhất mà các giao diện đi vào hoạt động ở đây là trong việc cung cấp dữ liệu, ví dụ: ITableDataAdapterliên kết dữ liệu với điều khiển bảng. Đây chính xác là loại giao diện điều được dùng để có hành vi hoán đổi cho nhau .


0

Trong Java lý do là các giao diện chỉ cho phép các phương thức chỉ định .

Do đó, nếu bạn muốn bất cứ điều gì với một trường trong hợp đồng giao diện, bạn cần thực hiện nó như một phương thức getter và setter.

Cũng xem câu hỏi này: Khi nào Getters và Setters được chứng minh


1
Cảm ơn bạn đã đến để trả lời, thực ra câu trả lời của bạn về chính chủ đề đó đã khiến tôi phải hỏi câu hỏi này :) Nhưng câu hỏi vẫn còn, "-WHY- họ có chỉ cho phép các phương pháp không?" Điểm của giao diện là không chỉ định các phương thức, đó là logic theo chu kỳ. Điểm quan trọng của các giao diện là đảm bảo rằng một số mức độ cơ bản của chức năng được đáp ứng. Thành viên có thể tạo nên một phần của chức năng đó. Vậy tại sao không cho phép họ tham gia vào việc thực hiện giao diện?
Kỹ sư

Tôi không biết. Có lẽ nếu bạn hỏi trực tiếp Gosling hoặc Steele?

-1

Điểm quan trọng của giao diện là chỉ định các chức năng bạn phải triển khai để yêu cầu hỗ trợ giao diện này.


2
Điều này không trả lời câu hỏi. Câu hỏi là TẠI SAO họ đã làm theo cách đó? Bạn đã bao giờ cân nhắc việc không viết getters và setters cho mỗi biến, và vẫn có thể hoàn thành một giao diện? Điều đó sẽ tiết kiệm thời gian!
Kỹ sư

Bạn cứ hỏi về getters và setters, và tôi không biết tại sao. Nhìn vào một giao diện đơn giản: download.oracle.com/javase/6/docs/api/java/util/NH Thông báo làm thế nào không có getters và setters?
Scott C Wilson

1
Điều đó chứng tỏ điều gì? Có phải một ví dụ chứng minh bạn sẽ không bao giờ cần truy cập đơn giản / trực tiếp đến các thành viên? Vấn đề là, thật ngớ ngẩn khi bao bọc các thành viên trong getters / setters như một phần của giao diện, nếu chính ngôn ngữ có thể tự động xử lý điều đó.
Kỹ sư

Có hàng trăm ví dụ khác giống như thế này. Bạn có thể cho tôi một ví dụ về tình huống bạn đang nói về?
Scott C Wilson

-1

Các thành viên không được phép trong các giao diện bởi vì sau đó những ngôn ngữ đó sẽ phải đối phó với cái ác khủng khiếp đó là sự thừa kế nhiều lần.


2
Không chắc tôi làm theo. Tại sao cho phép các biến thành viên trong giao diện yêu cầu hoặc ngụ ý hỗ trợ cho nhiều kế thừa?
Steve Mallam
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.