Các phương thức tùy chọn trong giao diện Java


120

Theo hiểu biết của tôi nếu bạn triển khai một giao diện trong java, các phương thức được chỉ định trong giao diện đó phải được sử dụng bởi các lớp con triển khai giao diện đã nói.

Tôi nhận thấy rằng trong một số giao diện chẳng hạn như giao diện Bộ sưu tập, có các phương thức được nhận xét là tùy chọn, nhưng chính xác thì điều này có nghĩa là gì? Nó ném cho tôi một chút vì tôi nghĩ rằng tất cả các phương thức được chỉ định trong giao diện sẽ được yêu cầu?


Bạn đang tham khảo những phương pháp nào? Tôi không thể tìm thấy nó trong JavaDoc hoặc mã nguồn
dcpomero


Câu trả lời:


232

Có vẻ như có rất nhiều sự nhầm lẫn trong các câu trả lời ở đây.

Ngôn ngữ Java yêu cầu mọi phương thức trong một giao diện được thực hiện bởi mọi quá trình thực thi của giao diện đó. Giai đoạn = Stage. Không có ngoại lệ cho quy tắc này. Để nói "Bộ sưu tập là một ngoại lệ" cho thấy sự hiểu biết rất mờ nhạt về những gì thực sự đang diễn ra ở đây.

Điều quan trọng là phải nhận ra rằng có hai cấp độ tuân theo giao diện:

  1. Những gì ngôn ngữ Java có thể kiểm tra. Điều này khá nhiều chỉ tóm tắt ở chỗ: có một số cách triển khai cho mỗi phương pháp không?

  2. Thực tế là hoàn thành hợp đồng. Đó là, việc triển khai có thực hiện những gì tài liệu trong giao diện cho biết nó phải không?

    Các giao diện được viết tốt sẽ bao gồm tài liệu giải thích chính xác những gì được mong đợi từ việc triển khai. Trình biên dịch của bạn không thể kiểm tra điều này cho bạn. Bạn cần đọc tài liệu và làm những gì họ nói. Nếu bạn không làm những gì hợp đồng quy định thì bạn sẽ có một triển khai giao diện theo như trình biên dịch có liên quan, nhưng nó sẽ là một triển khai bị lỗi / không hợp lệ.

Khi thiết kế API bộ sưu tập, Joshua Bloch đã quyết định rằng thay vì có các giao diện rất chi tiết để phân biệt giữa các biến thể khác nhau của bộ sưu tập (ví dụ: có thể đọc, có thể ghi, truy cập ngẫu nhiên, v.v.), anh ấy chỉ có một bộ giao diện rất thô, chủ yếu Collection, List, SetMap, và sau đó ghi lại một số hoạt động như là "bắt buộc". Điều này là để tránh sự bùng nổ tổ hợp xảy ra từ các giao diện chi tiết. Từ Câu hỏi thường gặp về Thiết kế API Bộ sưu tập Java :

Để minh họa vấn đề một cách chi tiết, giả sử bạn muốn thêm khái niệm về khả năng sửa đổi vào Hệ thống phân cấp. Bạn cần bốn giao diện mới: ModifiableCollection, ModifiableSet, ModifiableList và ModifiableMap. Những gì trước đây là một hệ thống phân cấp đơn giản bây giờ là một hệ thống phân cấp lộn xộn. Ngoài ra, bạn cần một giao diện Iterator mới để sử dụng với Bộ sưu tập không thể sửa đổi, không chứa thao tác xóa. Bây giờ bạn có thể làm gì với UnsupportedOperationException không? Không may măn.

Xem xét các mảng. Họ thực hiện hầu hết các hoạt động của Danh sách, nhưng không xóa và thêm. Chúng là các Danh sách "kích thước cố định". Nếu bạn muốn nắm bắt khái niệm này trong hệ thống phân cấp, bạn phải thêm hai giao diện mới: VariableSizeList và VariableSizeMap. Bạn không cần phải thêm VariableSizeCollection và VariableSizeSet, bởi vì chúng giống hệt với ModifiableCollection và ModifiableSet, nhưng bạn vẫn có thể chọn thêm chúng vì sự nhất quán. Ngoài ra, bạn cần một loạt ListIterator mới không hỗ trợ các thao tác thêm và xóa, cùng với Danh sách không thể sửa đổi. Bây giờ chúng tôi có tới mười hoặc mười hai giao diện, cộng với hai giao diện Iterator mới, thay vì bốn giao diện ban đầu của chúng tôi. Chúng ta xong chưa? Không.

Xem xét nhật ký (chẳng hạn như nhật ký lỗi, nhật ký kiểm tra và nhật ký cho các đối tượng dữ liệu có thể phục hồi). Chúng là các trình tự chỉ phần phụ tự nhiên, hỗ trợ tất cả các hoạt động của Danh sách ngoại trừ loại bỏ và đặt (thay thế). Chúng yêu cầu một giao diện cốt lõi mới và một trình lặp mới.

Và những gì về Bộ sưu tập bất biến, trái ngược với những Bộ sưu tập không thể thay đổi? (tức là, các Bộ sưu tập mà khách hàng không thể thay đổi VÀ sẽ không bao giờ thay đổi vì bất kỳ lý do nào khác). Nhiều người cho rằng đây là điểm khác biệt quan trọng nhất, vì nó cho phép nhiều luồng truy cập đồng thời vào một tập hợp mà không cần đồng bộ hóa. Việc thêm hỗ trợ này vào hệ thống phân cấp kiểu yêu cầu thêm bốn giao diện.

Bây giờ chúng tôi có tới hơn hai mươi giao diện và năm trình lặp, và gần như chắc chắn rằng vẫn có những tập hợp phát sinh trong thực tế không phù hợp rõ ràng với bất kỳ giao diện nào. Ví dụ: các chế độ xem bộ sưu tập được Bản đồ trả về là các bộ sưu tập chỉ xóa tự nhiên. Ngoài ra, có những bộ sưu tập sẽ từ chối các phần tử nhất định trên cơ sở giá trị của chúng, vì vậy chúng tôi vẫn chưa loại bỏ các ngoại lệ thời gian chạy.

Khi tất cả đã được nói và thực hiện, chúng tôi cảm thấy rằng đó là một thỏa hiệp kỹ thuật âm thanh để tránh toàn bộ vấn đề bằng cách cung cấp một tập hợp rất nhỏ các giao diện cốt lõi có thể tạo ra một ngoại lệ thời gian chạy.

Khi các phương thức trong API Bộ sưu tập được ghi nhận là "hoạt động tùy chọn", điều đó không có nghĩa là bạn có thể bỏ qua việc triển khai phương thức trong quá trình triển khai, cũng không có nghĩa là bạn có thể sử dụng phần thân phương thức trống (đối với một điều, nhiều chúng cần trả về một kết quả). Thay vào đó, nó có nghĩa là một lựa chọn thực hiện hợp lệ (một lựa chọn vẫn phù hợp với hợp đồng) là ném một UnsupportedOperationException.

Lưu ý rằng vì UnsupportedOperationExceptionlà một, RuntimeExceptionbạn có thể ném nó khỏi bất kỳ triển khai phương thức nào, theo như trình biên dịch có liên quan. Ví dụ, bạn có thể ném nó từ một triển khai của Collection.size(). Tuy nhiên, việc triển khai như vậy sẽ vi phạm hợp đồng vì tài liệu Collection.size()không nói rằng điều này được phép.

Bên cạnh đó: Cách tiếp cận được sử dụng bởi API Collections của Java có phần gây tranh cãi (tuy nhiên, có lẽ bây giờ ít hơn so với khi nó được giới thiệu lần đầu tiên). Trong một thế giới hoàn hảo, các giao diện sẽ không có các hoạt động tùy chọn và thay vào đó, các giao diện chi tiết sẽ được sử dụng. Vấn đề là Java không hỗ trợ các kiểu cấu trúc suy luận hoặc kiểu giao nhau, đó là lý do tại sao việc cố gắng thực hiện mọi thứ theo "cách đúng" lại trở nên cực kỳ khó sử dụng trong trường hợp tập hợp.


30
+1 cho There are no exceptions to this rule. Tự hỏi tại sao câu trả lời này không được đánh dấu là được chấp nhận. Những người khác là tốt nhưng bạn đã cho quá đủ.
xyz

9
"Ngôn ngữ Java yêu cầu rằng mọi phương thức trong một giao diện được thực hiện bởi mọi quá trình triển khai của giao diện đó. Giai đoạn. Không có ngoại lệ cho quy tắc này." Ngoại trừ ... khi có. :-) Các giao diện Java 8 có thể chỉ định một phương thức thực thi mặc định, Vì vậy, trong Java 8 ... KHÔNG đúng là mọi phương thức trong một giao diện phải được THỰC HIỆN BỞI mọi việc triển khai giao diện, ít nhất là không theo nghĩa mà bạn phải mã việc thực hiện trong lớp conrete.
DaBlick

1
@DaBlick Khi tôi nói "được thực hiện bởi mọi quá trình triển khai", tôi không có nghĩa là việc triển khai phương thức đã nói phải nằm trong nguồn của lớp thực thi. Ngay cả trước Java 8, người ta có thể kế thừa việc triển khai một phương thức giao diện, ngay cả từ một lớp không triển khai giao diện nói trên. ví dụ: tạo Foomà không thực hiện Runnablevới phương thức công khai void run(). Bây giờ tạo ra một lớp Barextends Fooimplements Runnablekhông overiding run. Nó vẫn thực hiện phương pháp, mặc dù gián tiếp. Tương tự như vậy, một triển khai phương pháp mặc định vẫn là một triển khai.
Laurence Gonsalves

Xin lỗi. Tôi đã không cố gắng chỉ trích quá nhiều để thu hút sự chú ý đến một tính năng Java 8 có thể liên quan đến bài đăng gốc. Trong Java 8, bây giờ bạn có tùy chọn có các triển khai không được mã hóa trong BẤT KỲ lớp siêu cấp hay lớp con nào. Điều này (IMHO) mở ra một thế giới mới về các mẫu thiết kế bao gồm một số mẫu có thể phù hợp trong các trường hợp mà lệnh cấm đa thừa kế có thể gây ra một số thách thức. Tôi nghĩ rằng đây sẽ đẻ trứng một bộ mới của các mẫu thiết kế rất hữu ích \.
DaBlick

3
@AndrewS vì trong Java 8 removeđã được cung cấp một cài đặt mặc định. Nếu bạn không triển khai nó, thì lớp của bạn sẽ nhận được cài đặt mặc định. Hai phương pháp khác mà bạn đề cập không có triển khai mặc định.
Laurence Gonsalves

27

Để biên dịch một lớp thực thi (không trừu tượng) cho một giao diện - tất cả các phương thức phải được thực hiện.

Tuy nhiên , nếu chúng ta nghĩ về một phương thức mà việc triển khai nó là một ngoại lệ đơn giản như một 'không được thực hiện' (giống như một số phương thức trong Collectiongiao diện), thì Collectiongiao diện là ngoại lệ trong trường hợp này, không phải trường hợp thông thường. Thông thường , lớp thực thi nên (và sẽ) thực hiện tất cả các phương thức.

"Tùy chọn" trong bộ sưu tập có nghĩa là lớp thực thi không phải 'thực hiện' (theo thuật ngữ ở trên) nó, và nó sẽ chỉ ném NotSupportedException).

Một ví dụ điển hình - add()phương pháp cho các tập hợp bất biến - cụ thể sẽ chỉ thực hiện một phương thức không làm gì khác ngoài việc némNotSupportedException

Trong trường hợp Collectionnó được thực hiện để ngăn chặn các cây kế thừa lộn xộn, điều đó sẽ làm cho các lập trình viên khốn khổ - nhưng đối với hầu hết các trường hợp, mô hình này không được khuyến khích và nên tránh nếu có thể.


Cập nhật:

Kể từ java 8, một phương pháp mặc định đã được giới thiệu.

Điều đó có nghĩa là, một giao diện có thể xác định một phương thức - bao gồm cả việc triển khai nó.
Điều này đã được thêm vào để cho phép thêm chức năng vào các giao diện, trong khi vẫn hỗ trợ khả năng tương thích ngược cho các đoạn mã không cần chức năng mới.

Lưu ý rằng phương thức vẫn được thực hiện bởi tất cả các lớp khai báo nó, nhưng sử dụng định nghĩa của giao diện.


Thay vì "không làm rối tung lên", tôi nghĩ nó đúng hơn là "chỉ có vậy thôi".

@pst: Tôi tin rằng những gì các nhà thiết kế đã nghĩ khi thực hiện nó ngay từ đầu, nhưng tôi không có cách nào để biết chắc chắn. Tôi nghĩ rằng bất kỳ cách tiếp cận nào khác sẽ chỉ tạo ra một mớ hỗn độn, nhưng một lần nữa - có thể sai. Điểm tôi cố gắng chỉ ra ở đây là: Ví dụ này là ngoại lệ, không phải thông thường - và mặc dù đôi khi nó có thể hữu ích - đối với trường hợp chung - nên tránh, nếu có thể.
amit

12
"không cần phải thực hiện nó (Nó có thể sẽ chỉ tạo ra một phương thức ném ...)". Đó thực hiện phương pháp.
Marquis of Lorne,

1
Rất tiếc, đây là câu trả lời được chấp nhận, tôi khuyên bạn nên viết lại nó. ' Thông thường , lớp triển khai nên (và sẽ) triển khai tất cả các phương thức' là sai lầm như EJP đã chỉ ra.
Alberto

2
. Các "bắt buộc" trong phương tiện sưu tập mà các lớp thực hiện không nhất thiết phải thực hiện nó" - đây là đồng bằng sai Bằng. 'Không nhất thiết phải thực hiện' bạn có nghĩa là cái gì khác.
djechlin

19

Một giao diện trong Java chỉ khai báo hợp đồng để triển khai các lớp. Tất cả các phương thức trong giao diện đó phải được triển khai, nhưng các lớp thực thi được tự do để chúng chưa hoàn thành, viz., Trống. Như một ví dụ giả định,

interface Foo {
  void doSomething();
  void doSomethingElse();
}

class MyClass implements Foo {
  public void doSomething() {
     /* All of my code goes here */
  }

  public void doSomethingElse() {
    // I leave this unimplemented
  }
}

Bây giờ tôi vẫn doSomethingElse()chưa hoàn thành, để nó tự do cho các lớp con của tôi thực hiện. Đó là tùy chọn.

class SubClass extends MyClass {
    @Override
    public void doSomethingElse() {
      // Here's my implementation. 
    }
}

Tuy nhiên, nếu bạn đang nói về giao diện Bộ sưu tập, như những người khác đã nói, chúng là một ngoại lệ. Nếu một số phương thức nhất định không được thực hiện và bạn gọi chúng, chúng có thể ném ra các UnsupportedOperationExceptionngoại lệ.


Tôi có thể hôn bạn, bạn của tôi.
Vi

16

Các phương thức tùy chọn trong giao diện Bộ sưu tập có nghĩa là việc triển khai phương thức được phép đưa ra một ngoại lệ, nhưng nó vẫn phải được triển khai. Như được chỉ định trong tài liệu :

Một số triển khai bộ sưu tập có các hạn chế đối với các phần tử mà chúng có thể chứa. Ví dụ: một số triển khai cấm các phần tử rỗng và một số có các hạn chế về loại phần tử của chúng. Việc cố gắng thêm một phần tử không đủ điều kiện sẽ ném ra một ngoại lệ không được chọn, thường là NullPointerException hoặc ClassCastException. Cố gắng truy vấn sự hiện diện của một phần tử không đủ điều kiện có thể tạo ra một ngoại lệ, hoặc nó có thể chỉ trả về false; một số triển khai sẽ thể hiện hành vi trước đây và một số sẽ thể hiện hành vi sau. Nói một cách tổng quát hơn, việc cố gắng thực hiện một phần tử không đủ điều kiện mà việc hoàn thành sẽ không dẫn đến việc chèn phần tử không đủ điều kiện vào bộ sưu tập có thể tạo ra một ngoại lệ hoặc nó có thể thành công, theo tùy chọn triển khai. Những ngoại lệ như vậy được đánh dấu là "tùy chọn"


Tôi chưa bao giờ thực sự hiểu javadocs có nghĩa là tùy chọn. Tôi tin rằng họ có ý nghĩa như bạn đã nói. Nhưng hầu hết các phương pháp là không bắt buộc theo tiêu chuẩn đó: new Runnable ( ) { @ Override public void run ( ) { throw new UnsupportedOperationException ( ) ; } };
emory

Điều này dường như không áp dụng cho các phương thức tùy chọn , nhưng thay vào đó, ví dụ, add((T)null)có thể hợp lệ trong trường hợp này nhưng không hợp lệ trong trường hợp khác. Nghĩa là, điều này nói về các ngoại lệ / hành vi tùy chọn và đối số ("hạn chế đối với phần tử" ... "phần tử không đủ điều kiện" ... "ngoại lệ được đánh dấu là tùy chọn") và không đề cập đến các phương thức tùy chọn .

9

Tất cả các phương thức phải được triển khai để mã biên dịch, (ngoại trừ những phương thức có defaulttriển khai trong Java 8+), nhưng việc triển khai không phải làm bất cứ điều gì hữu ích về mặt chức năng. Cụ thể, nó:

  • Có thể để trống (một phương thức trống.)
  • Có thể chỉ cần ném một UnsupportedOperationException(hoặc tương tự)

Cách tiếp cận thứ hai thường được thực hiện trong các lớp thu thập - tất cả các phương thức vẫn được thực hiện, nhưng một số phương thức có thể ném ra một ngoại lệ nếu được gọi trong thời gian chạy.


5

Trên thực tế, tôi lấy cảm hứng từ SurfaceView.Callback2. Tôi nghĩ đây là cách chính thức

public class Foo {
    public interface Callback {
        public void requiredMethod1();
        public void requiredMethod2();
    }

    public interface CallbackExtended extends Callback {
        public void optionalMethod1();
        public void optionalMethod2();
    }

    private Callback mCallback;
}

Nếu lớp của bạn không cần triển khai các phương thức tùy chọn, chỉ cần "thực hiện Gọi lại". Nếu lớp của bạn cần triển khai các phương thức tùy chọn, chỉ cần "thực hiện CallbackExtended".

Xin lỗi vì tiếng Anh tệ.


5

Trong Java 8 trở lên, câu trả lời cho câu hỏi này vẫn còn giá trị nhưng giờ đây đã có nhiều sắc thái hơn.

Đầu tiên, các câu sau từ câu trả lời được chấp nhận vẫn đúng:

  • các giao diện có nghĩa là để chỉ định các hành vi ngầm của chúng trong một hợp đồng (một tuyên bố về các quy tắc cho hành vi mà các lớp triển khai phải tuân theo để được coi là hợp lệ)
  • có sự khác biệt giữa hợp đồng (các quy tắc) và việc thực hiện (mã hóa theo chương trình của các quy tắc)
  • các phương thức được chỉ định trong giao diện PHẢI LUÔN được triển khai (tại một số thời điểm)

Vậy, sắc thái mới trong Java 8 là gì? Khi nói về "Phương pháp tùy chọn", bất kỳ điều nào sau đây đều phù hợp:

1. Một phương pháp mà việc triển khai là tùy chọn theo hợp đồng

"Câu lệnh thứ ba" nói rằng các phương thức giao diện trừu tượng phải luôn được thực hiện và điều này vẫn đúng trong Java 8+. Tuy nhiên, như trong Java Collections Framework, có thể mô tả một số phương thức giao diện trừu tượng là "tùy chọn" trong hợp đồng.

Trong trường hợp này, tác giả đang triển khai giao diện có thể chọn không triển khai phương pháp. Tuy nhiên, trình biên dịch sẽ nhấn mạnh vào việc triển khai và do đó tác giả sử dụng mã này cho bất kỳ phương thức tùy chọn nào không cần thiết trong lớp triển khai cụ thể:

public SomeReturnType optionalInterfaceMethodA(...) {
    throw new UnsupportedOperationException();
}

Trong Java 7 trở về trước, đây thực sự là loại "phương thức tùy chọn" duy nhất có, tức là một phương thức, nếu không được triển khai, sẽ ném ra một ngoại lệ UnsupportedOperationException. Hành vi này nhất thiết phải được quy định bởi hợp đồng giao diện (ví dụ: các phương thức giao diện tùy chọn của Java Collections Framework).

2. Một phương pháp mặc định có việc triển khai lại là tùy chọn

Java 8 đã giới thiệu khái niệm về các phương thức mặc định . Đây là những phương thức mà việc triển khai có thể được và được cung cấp bởi chính định nghĩa giao diện. Nói chung, chỉ có thể cung cấp các phương thức mặc định khi thân phương thức có thể được viết bằng các phương thức giao diện khác (tức là "nguyên thủy") và khi nào thiscó thể có nghĩa là "đối tượng này có lớp đã triển khai giao diện này."

Phương thức mặc định phải hoàn thành hợp đồng của giao diện (giống như bất kỳ phương thức triển khai phương thức giao diện nào khác). Do đó, việc chỉ định thực thi phương thức giao diện trong một lớp thực thi là tùy theo quyết định của tác giả (miễn là hành vi đó phù hợp với mục đích của họ).

Trong môi trường mới này, Java Collections Framework có thể được viết lại thành:

public interface List<E> {
    :
    :
    default public boolean add(E element) {
        throw new UnsupportedOperationException();
    }
    :
    :
}

Theo cách này, phương thức "tùy chọn" add()có hành vi mặc định là ném một UnsupportedOperationException nếu lớp thực thi không cung cấp hành vi mới của riêng nó, đó là chính xác những gì bạn muốn xảy ra và tuân thủ hợp đồng cho Danh sách. Nếu tác giả đang viết một lớp không cho phép các phần tử mới được thêm vào triển khai Danh sách, thì việc triển khai add()là tùy chọn vì hành vi mặc định là chính xác những gì cần thiết.

Trong trường hợp này, "câu lệnh thứ ba" ở trên vẫn đúng, vì phương thức đã được thực hiện trong chính giao diện.

3. Một phương thức trả về một Optionalkết quả

Loại phương thức tùy chọn mới cuối cùng chỉ đơn giản là một phương thức trả về một Optional. Các Optionallớp học cung cấp một cách hướng đối tượng decidedly hơn để đối phó với nullkết quả.

Trong một phong cách lập trình trôi chảy, chẳng hạn như kiểu thường thấy khi viết mã bằng Java Streams API mới, kết quả rỗng tại bất kỳ thời điểm nào khiến chương trình gặp sự cố với NullPointerException. Các Optionallớp học cung cấp một cơ chế để trả kết quả null để mã khách hàng theo một cách mà cho phép phong cách thành thạo mà không gây ra mã khách hàng để sụp đổ.


4

Nếu chúng ta xem qua mã của AbstractCollection.java trong grepCode, là lớp tổ tiên cho tất cả các triển khai bộ sưu tập, nó sẽ giúp chúng ta hiểu ý nghĩa của các phương thức tùy chọn. Đây là mã cho phương thức add (e) trong lớp AbstractCollection. phương thức add (e) là tùy chọn theo giao diện bộ sưu tập

public boolean  add(E e) {

        throw new UnsupportedOperationException();
    } 

Phương thức tùy chọn có nghĩa là nó đã được triển khai trong các lớp tổ tiên và nó ném UnsupportedOperationException khi gọi. Nếu chúng ta muốn làm cho bộ sưu tập của mình có thể sửa đổi được thì chúng ta nên ghi đè các phương thức tùy chọn trong giao diện bộ sưu tập.


4

Chà, chủ đề này đã được đề cập đến ... vâng .. nhưng hãy nghĩ xem, thiếu một câu trả lời. Tôi đang nói về "Phương thức mặc định" của giao diện. Ví dụ, hãy tưởng tượng bạn sẽ có một lớp để đóng bất cứ thứ gì (như hàm hủy hoặc thứ gì đó). Giả sử nó phải có 3 phương pháp. Hãy gọi chúng là "doFirst ()", "doLast ()" và "onClose ()".

Vì vậy, chúng tôi nói rằng chúng tôi muốn bất kỳ đối tượng nào thuộc kiểu đó ít nhất nhận ra "onClose ()", nhưng đối tượng khác là tùy chọn.

Bạn có thể nhận ra điều đó, bằng cách sử dụng "Phương pháp mặc định" của giao diện. Tôi biết, điều này hầu hết Thời gian sẽ phủ nhận lý do của một giao diện, nhưng nếu bạn đang thiết kế một khuôn khổ, điều này có thể hữu ích.

Vì vậy, nếu bạn muốn nhận ra nó theo cách này, nó sẽ trông như sau

public interface Closer {
    default void doFirst() {
        System.out.print("first ... ");
    }
    void onClose();
    default void doLast() {
        System.out.println("and finally!");
    }
}

Điều gì sẽ xảy ra bây giờ, nếu bạn ví dụ như triển khai nó trong một lớp có tên "Test", trình biên dịch sẽ hoàn toàn ổn với những điều sau:

public class TestCloser implements Closer {
    @Override
    public void onClose() {
        System.out.print("closing ... ");
    }
}

với Đầu ra:

first ... closing ... and finally!

hoặc là

public class TestCloser implements Closer {
    @Override
    public void onClose() {
        System.out.print("closing ... ");
    }

    @Override
    public void doLast() {
        System.out.println("done!");
    }
}

với đầu ra:

first ... closing ... done!

Tất cả các kết hợp đều có thể. Bất kỳ thứ gì có "mặc định" đều có thể được triển khai, nhưng không được, tuy nhiên bất kỳ thứ gì không có phải được thực hiện.

Hy vọng nó không hoàn toàn sai mà bây giờ tôi trả lời.

Một ngày tốt lành nhé mọi người!

[sửa1]: Xin lưu ý: Điều này chỉ hoạt động trong Java 8.


Vâng, xin lỗi, tôi quên đề cập đến điều này ... Nên được chỉnh sửa ngay bây giờ.
Thorben Kuck

1

Tôi đang tìm cách triển khai giao diện gọi lại, vì vậy việc triển khai các phương thức tùy chọn là cần thiết vì tôi không muốn triển khai mọi phương thức cho mỗi lần gọi lại.

Vì vậy, thay vì sử dụng một giao diện, tôi đã sử dụng một lớp có triển khai rỗng, chẳng hạn như:

public class MyCallBack{
    public void didResponseCameBack(String response){}
}

Và bạn có thể đặt CallBack biến thành viên như thế này,

c.setCallBack(new MyCallBack() {
    public void didResponseCameBack(String response) {
        //your implementation here
    }
});

sau đó gọi nó như thế này.

if(mMyCallBack != null) {
    mMyCallBack.didResponseCameBack(response);
}

Bằng cách này, bạn sẽ không cần phải lo lắng về việc triển khai mọi phương thức cho mỗi lần gọi lại, mà chỉ ghi đè những phương thức bạn cần.


0

Mặc dù nó không trả lời câu hỏi của OP, nhưng điều đáng chú ý là Java 8 thêm các phương thức mặc định vào giao diện trên thực tế là có thể làm được . Các defaulttừ khóa được đặt trong chữ ký phương pháp của một giao diện sẽ cho kết quả trong một lớp học có tùy chọn để ghi đè phương pháp, nhưng không yêu cầu nó.


0

Hướng dẫn Bộ sưu tập Java của Oracle:

Để giữ cho số lượng giao diện bộ sưu tập cốt lõi có thể quản lý được, nền tảng Java không cung cấp các giao diện riêng biệt cho từng biến thể của từng loại bộ sưu tập. (Các biến thể như vậy có thể bao gồm bất biến, kích thước cố định và chỉ phần phụ.) Thay vào đó, các hoạt động sửa đổi trong mỗi giao diện được chỉ định là tùy chọn - một triển khai nhất định có thể chọn không hỗ trợ tất cả các hoạt động. Nếu một hoạt động không được hỗ trợ được gọi ra, một bộ sưu tập sẽ ném ra một Ngoại lệ không được hỗ trợ . Các triển khai có trách nhiệm ghi lại các hoạt động tùy chọn mà chúng hỗ trợ. Tất cả các triển khai mục đích chung của nền tảng Java hỗ trợ tất cả các hoạt động tùy chọn.

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.