การสืบทอดหลายรายการสำหรับคลาสที่ไม่ระบุชื่อ


98

คลาสที่ไม่ระบุชื่อสามารถใช้สองอินเทอร์เฟซ (หรือมากกว่า) ได้อย่างไร? หรืออีกวิธีหนึ่งวิธีที่สามารถมันทั้งขยายชั้นเรียนและการใช้อินเตอร์เฟซอยู่แล้ว? ตัวอย่างเช่นฉันต้องการสร้างออบเจ็กต์ของคลาสที่ไม่ระบุชื่อที่ขยายสองอินเทอร์เฟซ:

    // Java 10 "var" is used since I don't know how to specify its type
    var lazilyInitializedFileNameSupplier = (new Supplier<String> implements AutoCloseable)() {
        private String generatedFileName;
        @Override
        public String get() { // Generate file only once
            if (generatedFileName == null) {
              generatedFileName = generateFile();
            }
            return generatedFileName;
        }
        @Override
        public void close() throws Exception { // Clean up
            if (generatedFileName != null) {
              // Delete the file if it was generated
              generatedFileName = null;
            }
        }
    };

จากนั้นฉันสามารถใช้มันในบล็อก try-with-resources เหมือนกับAutoCloseableคลาสยูทิลิตี้เริ่มต้นอย่างเฉื่อยชา:

        try (lazilyInitializedFileNameSupplier) {
            // Some complex logic that might or might not 
            // invoke the code that creates the file
            if (checkIfNeedToProcessFile()) {
                doSomething(lazilyInitializedFileNameSupplier.get());
            }
            if (checkIfStillNeedFile()) {
                doSomethingElse(lazilyInitializedFileNameSupplier.get());
            }
        } 
        // By now we are sure that even if the file was generated, it doesn't exist anymore

ฉันไม่ต้องการสร้างคลาสภายในเพราะฉันแน่ใจอย่างยิ่งว่าคลาสนี้จะไม่ถูกใช้ที่ใดก็ได้ยกเว้นวิธีที่ฉันต้องใช้ (และฉันอาจต้องการใช้ตัวแปรท้องถิ่นที่ประกาศในวิธีนั้นซึ่งอาจ เป็นvarประเภท)


น่าเสียดายที่คุณต้องทำให้ตัวสร้างมองเห็นได้ในสถานที่ที่ไม่เช่นนั้นจะไม่เป็นเช่นนั้น
Sridhar Sarnobat

คำตอบ:


101

เรียนไม่ประสงค์ออกนามต้องขยายหรือการดำเนินการบางสิ่งบางอย่างเช่น class Java อื่น ๆ java.lang.Objectถึงแม้ว่ามันจะเป็นเพียง

ตัวอย่างเช่น:

Runnable r = new Runnable() {
   public void run() { ... }
};

นี่เป็นวัตถุของชั้นที่ไม่ระบุชื่อซึ่งดำเนินrRunnable

คลาสที่ไม่ระบุชื่อสามารถขยายคลาสอื่นได้โดยใช้ไวยากรณ์เดียวกัน:

SomeClass x = new SomeClass() {
   ...
};

สิ่งที่คุณไม่สามารถทำได้คือใช้อินเทอร์เฟซมากกว่าหนึ่ง คุณต้องมีคลาสที่มีชื่อเพื่อทำเช่นนั้น อย่างไรก็ตามทั้งคลาสภายในที่ไม่ระบุชื่อหรือคลาสที่ระบุชื่อสามารถขยายได้มากกว่าหนึ่งคลาส


1
ฉันไม่คิดว่าสำนวนที่สองถูกต้อง คุณได้ประกาศชื่อคลาสเป็น SomeClass แล้ว แต่จะไม่เปิดเผยชื่ออีกต่อไป ตรวจสอบลิงค์นี้docstore.mik.ua/orelly/java-ent/jnut/ch03_12.htmเมื่อคุณ "ใหม่" อินเทอร์เฟซคลาสที่ไม่ระบุชื่อจะถูกสร้างขึ้นโดยการขยายคลาส "Object" และใช้งานอินเทอร์เฟซนั้น แต่ในขณะที่คุณกำลัง "สร้าง" คลาสที่มีนิพจน์แรกที่คุณเขียนคลาสที่ไม่ระบุตัวตน (อันที่จริงมันเป็นอินสแตนซ์ของคลาสที่ไม่ระบุชื่อนั้นถูกสร้างขึ้น) จะถูกสร้างขึ้นโดยการขยายคลาสนั้น
lixiang

8
@youmiss: การแสดงออกที่ 2 SomeClassจะสร้างตัวอย่างของการเรียนที่ไม่ระบุชื่อซึ่งทอดตัว ยังคงไม่ระบุชื่อเนื่องจากไฟล์{...}.
skaffman

1
ฉันเห็นฉันมองข้าม {... } ไป
lixiang

36

คลาสที่ไม่ระบุชื่อมักจะใช้อินเทอร์เฟซ:

new Runnable() { // implements Runnable!
   public void run() {}
}

JFrame.addWindowListener( new WindowAdapter() { // extends  class
} );

หากคุณหมายถึงว่าคุณสามารถใช้2อินเทอร์เฟซหรือมากกว่านั้นได้มากกว่าที่ฉันคิดว่าเป็นไปไม่ได้ จากนั้นคุณสามารถสร้างอินเทอร์เฟซส่วนตัวซึ่งรวมทั้งสองอย่างเข้าด้วยกัน แม้ว่าฉันจะนึกไม่ออกง่ายๆว่าทำไมคุณถึงต้องการให้คลาสนิรนามมีสิ่งนั้น:

 public class MyClass {
   private interface MyInterface extends Runnable, WindowListener { 
   }

   Runnable r = new MyInterface() {
    // your anonymous class which implements 2 interaces
   }

 }

ฉันชอบคำตอบนี้เพราะเป็นมิตรกับ Google สำหรับผู้ที่มองหาการใช้งานอินเทอร์เฟซตั้งแต่ 2 อินเทอร์เฟซขึ้นไป
L. Holanda

16

คลาสที่ไม่ระบุชื่อมักจะขยาย superclass หรือใช้อินเทอร์เฟซ ตัวอย่างเช่น:

button.addActionListener(new ActionListener(){ // ActionListener is an interface
    public void actionPerformed(ActionEvent e){
    }
});

ยิ่งไปกว่านั้นแม้ว่าคลาสที่ไม่ระบุชื่อจะไม่สามารถใช้หลายอินเทอร์เฟซได้ แต่คุณสามารถสร้างอินเทอร์เฟซที่ขยายส่วนต่อประสานอื่น ๆ และปล่อยให้คลาสที่ไม่ระบุชื่อของคุณนำไปใช้


13

ฉันเดาว่าไม่มีใครเข้าใจคำถาม ฉันเดาว่าผู้ชายคนนี้ต้องการอะไรเป็นอย่างนี้:

return new (class implements MyInterface {
    @Override
    public void myInterfaceMethod() { /*do something*/ }
});

เนื่องจากสิ่งนี้จะช่วยให้สิ่งต่างๆเช่นการใช้งานอินเทอร์เฟซหลาย ๆ

return new (class implements MyInterface, AnotherInterface {
    @Override
    public void myInterfaceMethod() { /*do something*/ }

    @Override
    public void anotherInterfaceMethod() { /*do something*/ }
});

มันจะดีจริงๆ แต่ที่ไม่ได้รับอนุญาตใน Java

สิ่งที่คุณสามารถทำคือการใช้การเรียนในท้องถิ่นภายในบล็อกวิธีการ:

public AnotherInterface createAnotherInterface() {
    class LocalClass implements MyInterface, AnotherInterface {
        @Override
        public void myInterfaceMethod() { /*do something*/ }

        @Override
        public void anotherInterfaceMethod() { /*do something*/ }
    }
    return new LocalClass();
}

ตรงนี้คือสิ่งที่ OP ตั้งใจ IMHO
DanielCuadra

ยกนิ้วให้สำหรับการตอบคำถามที่ถาม ซึ่งเป็นเรื่องปกติใน SO ที่ผู้คนชอบตอบสิ่งที่ควรถามไม่ใช่สิ่งที่ถูกถาม
mfaisalhyder

3
// The interface
interface Blah {
    void something();
}

...

// Something that expects an object implementing that interface
void chewOnIt(Blah b) {
    b.something();
}

...

// Let's provide an object of an anonymous class
chewOnIt(
    new Blah() {
        @Override
        void something() { System.out.println("Anonymous something!"); }
    }
);

1

คลาสที่ไม่ระบุชื่อกำลังขยายหรือใช้งานในขณะที่สร้างอ็อบเจ็กต์ตัวอย่างเช่น:

Interface in = new InterFace()
{

..............

}

ที่นี่คลาส anonymous กำลังใช้งาน Interface

Class cl = new Class(){

.................

}

ที่นี่ anonymous Class กำลังขยายคลาสนามธรรม


ฉันไม่เห็นความแตกต่าง ของคุณแตกต่างจากของฉันอย่างไร
trapedInBatcaveWithBAtman

สิ่งที่ดีและกะทัดรัดสิ่งที่ฉันคิดถึงในตัวคุณคือคำตอบเช่น "เสมอ" หรือ "ต้อง" :)
kiedysktos
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.