635 Stimmen

Können wir eine abstrakte Klasse instanziieren?

In einem meiner Interviews wurde ich gefragt: "Können wir eine abstrakte Klasse instanziieren?"

Meine Antwort war: "Nein, das können wir nicht". Aber der Interviewer sagte mir: "Falsch, wir können."

Ich habe ein wenig darüber gestritten. Dann sagte er mir, ich solle es zu Hause selbst versuchen.

abstract class my {
    public void mymethod() {
        System.out.print("Abstract");
    }
}

class poly {
    public static void main(String a[]) {
        my m = new my() {};
        m.mymethod();
    }
}

Hier erstelle ich eine Instanz meiner Klasse und rufe eine Methode der abstrakten Klasse auf. Kann mir das bitte jemand erklären? Habe ich mich bei meinem Vorstellungsgespräch wirklich geirrt?

4voto

Kas Punkte 3547

Das Erweitern einer Klasse bedeutet nicht, dass Sie die Klasse instanziieren. Tatsächlich erstellen Sie in Ihrem Fall eine Instanz der Unterklasse.

Ich bin mir ziemlich sicher, dass abstrakte Klassen das Initiieren nicht erlauben. Ich würde also sagen: Nein, man kann eine abstrakte Klasse nicht instanziieren. Aber Sie können sie erweitern / erben.

Sie können eine abstrakte Klasse nicht direkt instanziieren. Aber das bedeutet nicht, dass man nicht indirekt eine Instanz der Klasse (nicht wirklich eine Instanz der ursprünglichen abstrakten Klasse) erhalten kann. Ich meine, Sie können die ursprüngliche abstrakte Klasse nicht instanziieren, aber Sie können es:

  1. Eine leere Klasse erstellen
  2. Vererben von der abstrakten Klasse
  3. Instanziieren Sie die abgeleitete Klasse

Sie erhalten also über die Instanz der abgeleiteten Klasse Zugriff auf alle Methoden und Eigenschaften einer abstrakten Klasse.

4voto

vikas agrahari Punkte 396

Nein, eine abstrakte Klasse kann man nicht instanziieren, sondern nur eine anonyme Klasse, in der man abstrakte Methoden deklariert und nur konkrete Methoden definiert.

4voto

Picrochole Punkte 137

Es ist unmöglich, eine abstrakte Klasse zu instanziieren. Was man wirklich tun kann, ist, einige allgemeine Methoden in einer abstrakten Klasse zu implementieren und andere unimplementiert zu lassen (indem man sie als abstrakt deklariert) und sie von den konkreten Nachfolgern je nach Bedarf implementieren zu lassen. Dann kann man eine Fabrik erstellen, die eine Instanz dieser abstrakten Klasse (eigentlich ihren Implementierer) zurückgibt. In der Fabrik entscheiden Sie dann, welchen Implementierer Sie wählen. Dies ist als Factory Design Pattern bekannt:

   public abstract class AbstractGridManager {
        private LifecicleAlgorithmIntrface lifecicleAlgorithm;
        // ... more private fields

        //Method implemented in concrete Manager implementors 
        abstract public Grid initGrid();

        //Methods common to all implementors
        public Grid calculateNextLifecicle(Grid grid){
            return this.getLifecicleAlgorithm().calculateNextLifecicle(grid);
        }

        public LifecicleAlgorithmIntrface getLifecicleAlgorithm() {
            return lifecicleAlgorithm;
        }
        public void setLifecicleAlgorithm(LifecicleAlgorithmIntrface lifecicleAlgorithm) {
            this.lifecicleAlgorithm = lifecicleAlgorithm;
        }
        // ... more common logic and getters-setters pairs
    }

Der konkrete Implementierer muss nur die als abstrakt deklarierten Methoden implementieren, hat aber Zugriff auf die Logik, die in den nicht als abstrakt deklarierten Klassen in einer abstrakten Klasse implementiert ist:

public class FileInputGridManager extends AbstractGridManager {

private String filePath;

//Method implemented in concrete Manager implementors 
abstract public Grid initGrid();

public class FileInputGridManager extends AbstractGridManager {

    private String filePath;

    //Method implemented in concrete Manager implementors 
    abstract public Grid initGrid();

    public Grid initGrid(String filePath) {
        List<Cell> cells = new ArrayList<>();
        char[] chars;
        File file = new File(filePath); // for example foo.txt
        // ... more logic
        return grid;
    }
}

Dann sieht das Werk schließlich so aus:

public class GridManagerFactory {
    public static AbstractGridManager getGridManager(LifecicleAlgorithmIntrface lifecicleAlgorithm, String... args){
        AbstractGridManager manager = null;

        // input from the command line
        if(args.length == 2){
            CommandLineGridManager clManager = new CommandLineGridManager();
            clManager.setWidth(Integer.parseInt(args[0]));
            clManager.setHeight(Integer.parseInt(args[1]));
            // possibly more configuration logic
            ...
            manager = clManager;
        } 
        // input from the file
        else if(args.length == 1){
            FileInputGridManager fiManager = new FileInputGridManager();
            fiManager.setFilePath(args[0]);
            // possibly more method calls from abstract class
            ...
            manager = fiManager ;
        }
        //... more possible concrete implementors
        else{
            manager = new CommandLineGridManager();
        }
        manager.setLifecicleAlgorithm(lifecicleAlgorithm);
        return manager;
    }
}

Der Empfänger von AbstractGridManager würde die Methoden von AbstractGridManager aufrufen und die Logik erhalten, die im konkreten Deszendenten (und teilweise in den Methoden der abstrakten Klasse) implementiert ist, ohne zu wissen, was die konkrete Implementierung ist, die er erhält. Dies wird auch als Inversion der Kontrolle oder Dependency Injection bezeichnet.

4voto

Eddy Punkte 3225

Sie können sagen:
können wir eine abstrakte Klasse nicht instanziieren, aber wir können new Schlüsselwort, um eine anonyme Klasseninstanz zu erstellen, indem Sie einfach {} als Implementierungskörper am Ende der abstrakten Klasse.

2voto

Ketan G Punkte 497

Nein, wir können nicht das Objekt einer abstrakten Klasse erstellen, sondern die Referenzvariable der abstrakten Klasse erstellen. Die Referenzvariable wird verwendet, um auf die Objekte der abgeleiteten Klassen (Unterklassen der abstrakten Klasse) zu verweisen.

Hier ein Beispiel, das dieses Konzept veranschaulicht

abstract class Figure { 

    double dim1; 

    double dim2; 

    Figure(double a, double b) { 

        dim1 = a; 

        dim2 = b; 

    } 

    // area is now an abstract method 

    abstract double area(); 

    }

    class Rectangle extends Figure { 
        Rectangle(double a, double b) { 
        super(a, b); 
    } 
    // override area for rectangle 
    double area() { 
        System.out.println("Inside Area for Rectangle."); 
        return dim1 * dim2; 
    } 
}

class Triangle extends Figure { 
    Triangle(double a, double b) { 
        super(a, b); 
    } 
    // override area for right triangle 
    double area() { 
        System.out.println("Inside Area for Triangle."); 
        return dim1 * dim2 / 2; 
    } 
}

class AbstractAreas { 
    public static void main(String args[]) { 
        // Figure f = new Figure(10, 10); // illegal now 
        Rectangle r = new Rectangle(9, 5); 
        Triangle t = new Triangle(10, 8); 
        Figure figref; // this is OK, no object is created 
        figref = r; 
        System.out.println("Area is " + figref.area()); 
        figref = t; 
        System.out.println("Area is " + figref.area()); 
    } 
}

Hier sehen wir, dass wir das Objekt vom Typ Figure nicht erstellen können, aber wir können eine Referenzvariable vom Typ Figure erstellen. Hier haben wir eine Referenzvariable vom Typ Figure erstellt und die Referenzvariable der Klasse Figure wird verwendet, um auf die Objekte der Klassen Rechteck und Dreieck zu verweisen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X