เป็นไปได้ไหมที่จะสร้างคลาสภายในภายในอินเทอร์เฟซ
ถ้าเป็นไปได้เหตุใดเราจึงต้องการสร้างคลาสภายในเช่นนั้นเนื่องจากเราจะไม่สร้างวัตถุอินเทอร์เฟซใด ๆ
ชั้นเรียนภายในเหล่านี้ช่วยในกระบวนการพัฒนาหรือไม่?
เป็นไปได้ไหมที่จะสร้างคลาสภายในภายในอินเทอร์เฟซ
ถ้าเป็นไปได้เหตุใดเราจึงต้องการสร้างคลาสภายในเช่นนั้นเนื่องจากเราจะไม่สร้างวัตถุอินเทอร์เฟซใด ๆ
ชั้นเรียนภายในเหล่านี้ช่วยในกระบวนการพัฒนาหรือไม่?
คำตอบ:
ได้คุณสามารถสร้างทั้งคลาสที่ซ้อนกันหรือคลาสภายในภายในอินเทอร์เฟซ Java (โปรดทราบว่าในทางตรงกันข้ามกับความเชื่อที่เป็นที่นิยมไม่มีสิ่งที่เรียกว่า " คลาสภายในแบบคงที่ " สิ่งนี้ไม่สมเหตุสมผลไม่มีอะไร "ภายใน" และไม่ใช่ " outter "class เมื่อคลาสที่ซ้อนกันเป็นแบบคงที่ดังนั้นจึงไม่สามารถเป็น" static inner ")
อย่างไรก็ตามการคอมไพล์ต่อไปนี้ดี:
public interface A {
class B {
}
}
ฉันเคยเห็นมันเคยใส่ "ตัวตรวจสอบสัญญา" บางประเภทไว้ในคำจำกัดความของอินเทอร์เฟซโดยตรง (ในคลาสที่ซ้อนอยู่ในอินเทอร์เฟซที่สามารถมีวิธีการคงที่ขัดแย้งกับอินเทอร์เฟซเองซึ่งทำไม่ได้) มองแบบนี้ถ้าจำไม่ผิด
public interface A {
static class B {
public static boolean verifyState( A a ) {
return (true if object implementing class A looks to be in a valid state)
}
}
}
โปรดทราบว่าฉันไม่ได้แสดงความคิดเห็นเกี่ยวกับประโยชน์ของสิ่งนั้นฉันเพียงแค่ตอบคำถามของคุณ: สามารถทำได้และนี่คือการใช้งานประเภทหนึ่งที่ฉันเคยเห็นมา
ตอนนี้ฉันจะไม่แสดงความคิดเห็นเกี่ยวกับประโยชน์ของโครงสร้างดังกล่าวและจากที่ฉันเคยเห็นฉันเคยเห็นมาแล้ว แต่มันไม่ใช่โครงสร้างทั่วไป
200KLOC codebase ที่นี่ซึ่งสิ่งนี้เกิดขึ้นตรงเวลาเป็นศูนย์ (แต่จากนั้นเราก็มีสิ่งอื่น ๆ อีกมากมายที่เราพิจารณาการปฏิบัติที่ไม่ดีซึ่งเกิดขึ้นเป็นศูนย์เช่นกันซึ่งคนอื่น ๆ จะพบว่าปกติอย่างสมบูรณ์แบบ ... )
interface
s ไม่สามารถมีคลาสภายในได้ คุณสามารถละเว้นโมดิstatic
ฟายเออร์ของinterface
คลาสที่ซ้อนกันได้ แต่ยังคงเป็นคลาสที่ซ้อนกันไม่ใช่คลาสภายใน
B
คลาสนี้เป็นคลาสที่ซ้อนกันแบบคงที่ไม่ใช่คลาสภายใน อินเทอร์เฟซได้รับการดูแลเป็นพิเศษ ฉันไม่พบการพูดถึงเรื่องนี้ทางออนไลน์ยกเว้นในข้อมูลจำเพาะ: "คลาสสมาชิกของอินเทอร์เฟซเป็นแบบคงที่โดยปริยายดังนั้นจึงไม่ถือว่าเป็นคลาสภายใน" docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3
ใช่เราสามารถมีคลาสภายในอินเทอร์เฟซได้ ตัวอย่างหนึ่งของการใช้งานอาจเป็นได้
public interface Input
{
public static class KeyEvent {
public static final int KEY_DOWN = 0;
public static final int KEY_UP = 1;
public int type;
public int keyCode;
public char keyChar;
}
public static class TouchEvent {
public static final int TOUCH_DOWN = 0;
public static final int TOUCH_UP = 1;
public static final int TOUCH_DRAGGED = 2;
public int type;
public int x, y;
public int pointer;
}
public boolean isKeyPressed(int keyCode);
public boolean isTouchDown(int pointer);
public int getTouchX(int pointer);
public int getTouchY(int pointer);
public float getAccelX();
public float getAccelY();
public float getAccelZ();
public List<KeyEvent> getKeyEvents();
public List<TouchEvent> getTouchEvents();
}
ที่นี่โค้ดมีคลาสซ้อนกันสองคลาสซึ่งมีไว้สำหรับการห่อหุ้มข้อมูลเกี่ยวกับอ็อบเจ็กต์เหตุการณ์ซึ่งใช้ในภายหลังในนิยามเมธอดเช่น getKeyEvents () การมีไว้ในอินเทอร์เฟซอินพุตช่วยเพิ่มการทำงานร่วมกัน
การใช้งานที่ถูกต้อง IMHO กำลังกำหนดอ็อบเจ็กต์ที่ได้รับหรือส่งคืนโดยวิธีการเชื่อมต่อที่แนบมา โครงสร้างการจัดเก็บข้อมูลตามหลักการ ด้วยวิธีนี้หากใช้ออบเจ็กต์สำหรับอินเทอร์เฟซนั้นเท่านั้นคุณจะมีสิ่งต่างๆที่สอดคล้องกันมากขึ้น
ตามตัวอย่าง:
interface UserChecker {
Ticket validateUser(Credentials credentials);
class Credentials {
// user and password
}
class Ticket {
// some obscure implementation
}
}
แต่อย่างไรก็ตาม ... มันเป็นเรื่องของรสนิยมเท่านั้น
อ้างจากข้อมูลจำเพาะ Java 7 :
อินเทอร์เฟซอาจมีการประกาศประเภทสมาชิก (§8.5)
การประกาศประเภทสมาชิกในอินเทอร์เฟซเป็นแบบคงที่และเป็นสาธารณะโดยปริยาย ได้รับอนุญาตให้ระบุตัวดัดแปลงเหล่านี้หรือทั้งสองอย่างซ้ำซ้อน
เป็นไปไม่ได้ที่จะประกาศคลาสที่ไม่คงที่ภายในอินเทอร์เฟซ Java ซึ่งเหมาะสมกับฉัน
กรณีการใช้งานที่น่าสนใจคือการจัดเรียงการใช้งานเริ่มต้นกับวิธีการอินเทอร์เฟซผ่านคลาสภายในตามที่อธิบายไว้ที่นี่: https://stackoverflow.com/a/3442218/454667 (เพื่อเอาชนะปัญหาการสืบทอดคลาสเดียว)
เป็นไปได้อย่างแน่นอนและกรณีหนึ่งที่ฉันพบว่ามีประโยชน์คือเมื่ออินเทอร์เฟซต้องทิ้งข้อยกเว้นที่กำหนดเอง คุณเก็บข้อยกเว้นไว้กับอินเทอร์เฟซที่เกี่ยวข้องซึ่งฉันคิดว่ามักจะดีกว่าการทิ้งแผนผังซอร์สของคุณด้วยไฟล์ข้อยกเว้นเล็กน้อย
interface MyInterface {
public static class MyInterfaceException extends Exception {
}
void doSomething() throws MyInterfaceException;
}
ใช่มันเป็นไปได้ที่จะมีนิยามคลาสแบบคงที่ภายในอินเทอร์เฟซ แต่สิ่งที่เป็นประโยชน์ที่สุดของฟีเจอร์นี้ก็คือเมื่อใช้ประเภท enum (ซึ่งเป็นคลาสสแตติกชนิดพิเศษ) ตัวอย่างเช่นคุณสามารถมีสิ่งนี้:
public interface User {
public enum Role {
ADMIN("administrator"),
EDITOR("editor"),
VANILLA("regular user");
private String description;
private Role(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
public String getName();
public void setName(String name);
public Role getRole();
public void setRole(Role role);
...
}
สิ่งที่ @Bachi กล่าวถึงนั้นคล้ายกับลักษณะใน Scala และถูกนำไปใช้จริงโดยใช้คลาสที่ซ้อนกันภายในอินเทอร์เฟซ สิ่งนี้สามารถจำลองได้ใน Java ดูลักษณะ java หรือรูปแบบ mixins?
บางทีเมื่อคุณต้องการโครงสร้างที่ซับซ้อนมากขึ้นเช่นพฤติกรรมการใช้งานที่แตกต่างกันให้พิจารณา:
public interface A {
public void foo();
public static class B implements A {
@Override
public void foo() {
System.out.println("B foo");
}
}
}
นี่คืออินเทอร์เฟซของคุณและนี่คือเครื่องมือที่ใช้:
public class C implements A {
@Override
public void foo() {
A.B b = new A.B();
b.foo();
}
public static void main(String[] strings) {
C c = new C();
c.foo();
}
}
อาจมีการใช้งานแบบคงที่ แต่จะไม่ทำให้สับสนฉันไม่รู้
ฉันพบการใช้เฟอร์ประเภทนี้
คุณสามารถเข้าถึงค่าคงที่ทั้งหมดที่จัดกลุ่มไว้ ชื่อของคลาสทำหน้าที่เป็นเนมสเปซในกรณีนี้
คุณยังสามารถสร้างคลาสสแตติก "Helper" สำหรับฟังก์ชันการทำงานทั่วไปสำหรับอ็อบเจ็กต์ที่ใช้อินเทอร์เฟซนี้:
public interface A {
static class Helper {
public static void commonlyUsedMethod( A a ) {
...
}
}
}
ฉันต้องการมันตอนนี้ ฉันมีอินเทอร์เฟซที่สะดวกในการคืนคลาสเฉพาะจากหลาย ๆ วิธี คลาสนี้เป็นเพียงคอนเทนเนอร์สำหรับการตอบสนองจากวิธีการของอินเทอร์เฟซนี้
ดังนั้นจึงเป็นการสะดวกที่จะมีนิยามคลาสซ้อนแบบคงที่ซึ่งเชื่อมโยงกับอินเทอร์เฟซนี้เท่านั้นเนื่องจากอินเทอร์เฟซนี้ควรเป็นที่เดียวที่สร้างคลาสคอนเทนเนอร์ผลลัพธ์นี้
สำหรับลักษณะอินสแตนซ์(smth เช่นอินเทอร์เฟซที่มีวิธีการใช้งาน) ใน Groovy คอมไพล์ไปยังอินเทอร์เฟซที่มีคลาสภายในซึ่งใช้วิธีการทั้งหมด