Wywiad: czy możemy utworzyć klasę abstrakcyjną?

Ankieter zapytał - Czy możemy utworzyć instancję klasy abstrakcyjnej? Powiedziałem, Nie. Powiedział mi-źle, możemy.

Pokłóciłem się trochę o to. Potem powiedział mi, żebym spróbowała tego sama w Twoim domu.
abstract class my {
    public void mymethod() {
        System.out.print("Abstract");
    }
}

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

Tutaj tworzę instancję mojej klasy i wywołuję metodę klasy abstrakcyjnej. Czy ktoś może mi to wyjaśnić? Czy naprawdę myliłem się podczas rozmowy kwalifikacyjnej?

Author: user2864740, 2012-12-02

15 answers

Tutaj tworzę instancję mojej klasy

Nie, Nie tworzysz tutaj instancji swojej abstrakcyjnej klasy. Tworzysz raczej instancję anonimowej podklasy swojej klasy abstrakcyjnej. Następnie wywołujesz metodę na swojej klasie abstrakcyjnej referencji wskazującej na obiekt podklasy .

To zachowanie jest wyraźnie wymienione w JLS-sekcja # 15.9.1: -

Jeśli utworzenie instancji klasy wyrażenie kończy się ciałem klasowym, a następnie instancjowana klasa jest klasą anonimową. Wtedy:

  • Jeśli T oznacza klasę, to deklarowana jest anonimowa bezpośrednia podklasa klasy o nazwie T. Jest to błąd w czasie kompilacji, jeśli Klasa oznaczona przez T jest klasą końcową.
  • Jeśli T oznacza interfejs, to deklarowana jest anonimowa bezpośrednia podklasa obiektu implementująca interfejs nazwany przez T.
  • w obu przypadkach ciało podklasy jest ClassBody podane w wyrażeniu tworzenia instancji klasy.
  • klasa tworząca instancję jest podklasą anonimową.
/ Align = "left" /

Ponadto, w JLS-sekcja # 12.5, możesz przeczytać o procesie tworzenia obiektu. Przytoczę tu jedno stwierdzenie: -

Gdy tworzona jest nowa instancja klasy, przydzielana jest przestrzeń pamięci dla niego z miejscem dla wszystkich zmiennych instancji zadeklarowanych w Klasa typ i wszystkie zmienne instancji zadeklarowane w każdej superklasie typ klasy, zawierający wszystkie zmienne instancji, które mogą być ukryte.

Tuż przed odwołaniem do nowo utworzonego obiektu jest zwracane jako wynik, wskazany konstruktor jest przetwarzany w celu zainicjowania nowego obiekt wykorzystujący następującą procedurę:

Możesz przeczytać o całej procedurze na podanym przeze mnie linku.


Aby praktycznie zobaczyć, że klasa jest instantiated jest anonimową podklasą , wystarczy skompilować obie klasy. Załóżmy, że umieścisz te klasy w dwóch różnych plikach:

Ojej.java:

abstract class My {
    public void myMethod() {
        System.out.print("Abstract");
    }
}

Poly.java:

class Poly extends My {
    public static void main(String a[]) {
        My m = new My() {};
        m.myMethod();
    }
}

Teraz skompiluj oba pliki źródłowe:

javac My.java Poly.java

Teraz w katalogu, w którym skompilowałeś kod źródłowy, zobaczysz następujące pliki klas:

My.class
Poly$1.class  // Class file corresponding to anonymous subclass
Poly.class

Zobacz tę klasę - Poly$1.class. Jest to plik klasy utworzony przez kompilator odpowiadający anonimowa podklasa, którą utworzyłeś używając poniższego kodu:

new My() {};

Jest więc jasne, że istnieje inna klasa tworzona przez instancję. Chodzi o to, że ta klasa otrzymuje nazwę dopiero po kompilacji przez kompilator.

Ogólnie rzecz biorąc, wszystkie anonimowe podklasy w twojej klasie będą nazwane w ten sposób:

Poly$1.class, Poly$2.class, Poly$3.class, ... so on

Liczby te oznaczają kolejność, w jakiej te anonimowe klasy pojawiają się w klasie zamkniętej.

 675
Author: Rohit Jain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-26 10:51:59

Powyższe tworzy instancję anonimowej klasy wewnętrznej, która jest podklasą klasy abstrakcyjnej my. Nie jest to ściśle równoznaczne z utworzeniem instancji samej klasy abstrakcyjnej. OTOH, każda instancja podklasy jest instancją wszystkich jej superklas i interfejsów, więc większość abstrakcyjnych klas rzeczywiście tworzy instancję przez utworzenie jednej z ich konkretnych podklas.

Jeśli rozmówca po prostu powiedział " źle!"bez wyjaśnienia, i podał ten przykład, jako unikalny kontrprzykład, myślę, że on ale nie wie, o czym mówi.
 89
Author: JB Nizet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-09 05:39:43

= my() {}; oznacza to, że istnieje anonimowa implementacja, a nie prosta instancja obiektu, która powinna być : = my(). Nigdy nie można utworzyć abstrakcyjnej klasy.

 83
Author: Ioan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-02 12:09:00

Tylko spostrzeżenia, które możesz zrobić:

  1. dlaczego poly rozszerza my? To jest bezużyteczne...
  2. jaki jest Wynik kompilacji? Trzy pliki: my.class, poly.class oraz poly$1.class
  3. jeśli możemy utworzyć instancję abstrakcyjnej klasy, takiej jak ta, możemy utworzyć instancję interfejsu... dziwne...


Czy możemy utworzyć instancję klasy abstrakcyjnej?

Nie, Nie możemy. możemy stworzyć anonimową klasę (to trzeci plik) i utworzyć instancję to.


A co z instancją super klasy?

Abstrakcyjna super klasa nie jest tworzona przezus , ale przez Javę.

EDIT: poproś go o przetestowanie tego

public static final void main(final String[] args) {
    final my m1 = new my() {
    };
    final my m2 = new my() {
    };
    System.out.println(m1 == m2);

    System.out.println(m1.getClass().toString());
    System.out.println(m2.getClass().toString());

}

Wyjście to:

false
class my$1
class my$2
 29
Author: ncenerar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-11 10:26:06

Możesz po prostu odpowiedzieć w jednej linijce

Nie , nigdy nie możesz instancjonować klasy abstrakcyjnej

Ale, rozmówca nadal się nie zgadza, wtedy możesz mu/jej powiedzieć

Możesz tylko utworzyć anonimową klasę.

I, zgodnie z klasą anonimową, klasa zadeklarowana i instancyjna w tym samym miejscu / linii

Więc może być możliwe, że ankieter byłby zainteresowany, aby sprawdzić poziom zaufania i ile wiesz o UPS .

 18
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-07 04:14:18

Część techniczna została dobrze omówiona w innych odpowiedziach i kończy się głównie na:
"On się myli, nie wie rzeczy, poproś go, aby dołączył więc i wszystko wyjaśnione :)"

Chciałbym odnieść się do faktu (o którym wspomniano w innych odpowiedziach), że może to być stres-pytanie i jest ważnym narzędziem dla wielu ankieterów, aby dowiedzieć się więcej o Tobie i jak reagujesz na trudne i nietypowe sytuacje. Podając niepoprawne kody, on prawdopodobnie chciałem zobaczyć, czy się kłócicie. Aby wiedzieć, czy masz pewność, aby stanąć przeciwko swoim seniorom w sytuacjach podobnych do tego.

P. S: Nie wiem dlaczego, ale mam wrażenie, że rozmówca przeczytał ten post.

 16
Author: Mixcels,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-07 05:20:32

Klasy abstrakcyjne nie mogą być tworzone jako instancje, ale mogą być podklasowane. Zobacz Ten Link

Najlepszym przykładem jest

Chociaż Klasa Calender ma abstrakcyjną metodę getInstance () , ale kiedy mówisz Calendar calc=Calendar.getInstance();

Calc odnosi się do instancji klasy GregorianCalendar jako "GregorianCalendar extends Calendar "

Infact annonymous Typ wewnętrzny pozwala na utworzenie podklasy bez nazwy klasy abstrakcyjnej i przykład tego.

 13
Author: Abhishek_Mishra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-03 09:14:11

ODPOWIEDŹ Techniczna

Klasy abstrakcyjne nie mogą być utworzone-jest to z definicji i projektu.

Z JLS, Rozdział 8. Klasy:

nazwaną klasę można uznać za abstrakcyjną (§8.1.1.1) i należy ją zadeklarować abstrakcyjny, jeśli jest niekompletnie zaimplementowany; Klasa taka nie może być instancja, ale może być rozszerzona o podklasy.

Z JSE 6 java doc dla klas.newInstance ():

InstantiationException-jeśli ta klasa reprezentuje klasę abstrakcyjną, interfejs, tablicę klasy, typu prymitywnego lub void; lub jeśli klasa nie ma konstruktora zerowego; lub jeśli instancjacja nie powiodła się z jakiegoś innego powodu.

Możesz oczywiście utworzyć instancję konkretnej podklasy klasy abstrakcyjnej (w tym anonimowej podklasy), a także wykonać typecast odniesienia obiektu do typu abstrakcyjnego.

Inna Perspektywa - Teamplay & Inteligencja Społeczna:

Tego rodzaju techniczne nieporozumienia zdarzają się często w realnym świecie, kiedy mamy do czynienia ze złożonymi technologiami i legalistycznymi specyfikacjami.

"umiejętności ludzi" mogą być tutaj ważniejsze niż "umiejętności techniczne". Jeśli rywalizujesz i agresywnie próbujesz udowodnić swoją stronę argumentu, to teoretycznie możesz mieć rację, ale możesz też wyrządzić więcej szkód w walce / uszkodzeniu "twarzy" / stworzeniu wroga, niż jest to warte. Be pojednanie i zrozumienie w rozwiązywaniu różnic. Kto wie - może masz "obie rację", ale pracujesz nad nieco innymi znaczeniami dla terminów??

Kto wie-choć mało prawdopodobne, możliwe jest, że rozmówca celowo wprowadził mały konflikt/nieporozumienie, aby umieścić cię w trudnej sytuacji i zobaczyć, jak zachowujesz się emocjonalnie i społecznie. Bądź uprzejmy i konstruktywny w stosunku do kolegów, postępuj zgodnie z radami seniorów, a po rozmowie do rozwiąż wszelkie problemy/nieporozumienia - przez e-mail lub telefon. Pokazuje, że jesteś zmotywowany i zorientowany na szczegóły.

 11
Author: Glen Best,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-18 03:35:00

Jest to dobrze ugruntowany fakt, że abstract class możenie być instancją, jak każdy odpowiedział.

Kiedy program definiuje klasę anonimową, kompilator tworzy nową klasę o innej nazwie (ma wzorzec EnclosedClassName$n Gdzie n jest anonimowym numerem klasy)

Więc jeśli dekompilujesz tę klasę Javy, znajdziesz Kod jak poniżej:

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

Poli$1.class (wygenerowana Klasa " anonymous class")

class poly$1 extends my 
{
} 
Ploly.cass
public class poly extends my
{
    public static void main(String[] a)
    {
        my m = new poly.1(); // instance of poly.1 class NOT the abstract my class

        m.mymethod();
    }
}
 7
Author: iTech,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-14 12:33:26

Nie, Nie można tworzyć instancji klasy abstrakcyjnej.Tworzymy tylko anonimowe class.In klasa abstrakcyjna deklarujemy metody abstrakcyjne i definiujemy tylko konkretne metody.

 4
Author: vikas agrahari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-04 07:24:44

O Klasach Abstrakcyjnych

  • nie można utworzyć obiektu klasy abstrakcyjnej
  • może tworzyć zmienne (może zachowywać się jak typy danych)
  • jeśli dziecko nie może nadpisać co najmniej jednej abstrakcyjnej metody rodzica, wtedy dziecko również staje się abstrakcyjne
  • klasy abstrakcyjne są bezużyteczne bez klas dziecięcych

Celem klasy abstrakcyjnej jest zachowanie się jak Baza. W hierarchii dziedziczenia zobaczysz klasy abstrakcyjne w kierunku góry.

 4
Author: Priyankara,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-09 06:01:48

Możesz powiedzieć:
nie możemy utworzyć instancji klasy abstrakcyjnej, ale możemy użyć słowa kluczowego new do utworzenia anonimowej instancji klasy poprzez dodanie {} jako ciała implementacji na końcu klasy abstrakcyjnej.

 3
Author: Eddy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-19 11:33:06

Rozszerzenie klasy nie oznacza, że tworzysz instancję klasy. W Twoim przypadku tworzysz instancję podklasy.

Jestem prawie pewien, że klasy abstrakcyjne nie pozwalają na inicjowanie. Więc powiedziałbym Nie: Nie można utworzyć abstrakcyjnej klasy. Ale możesz go rozszerzyć / dziedziczyć.

Nie można bezpośrednio utworzyć instancji klasy abstrakcyjnej. Ale to nie znaczy, że nie można uzyskać instancji klasy (nie działać jako instancja oryginalnej abstrakcyjnej klasy) pośrednio. Chodzi mi o to, że nie możesz utworzyć instancji klasy abstrakcyjnej Orginalnej, ale możesz:

  1. Utwórz pustą klasę
  2. Dziedzicz go z klasy abstrakcyjnej
  3. Instantiate the dervied class

Więc uzyskujesz dostęp do wszystkich metod i właściwości w klasie abstrakcyjnej poprzez pochodną instancję klasy.

 3
Author: Kas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-09 05:46:22

Nie można utworzyć instancji klasy abstrakcyjnej. Co naprawdę można zrobić, ma zaimplementować niektóre wspólne metody w klasie abstrakcyjnej i niech inni nie zaimplementowane (deklarując je abstrakcyjne) i niech concrete descender zaimplementować je w zależności od ich potrzeb. Następnie można utworzyć fabrykę, która zwróci instancję tej abstrakcyjnej klasy (właściwie jego implementer). W fabryce to Ty decydujesz, który wykonawca wybrać. Jest to znane jako wzór fabryczny:

   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
    }

The concrete implementer musi tylko zaimplementować metody zadeklarowane jako abstrakcyjne, ale będzie miał dostęp do logiki zaimplementowanej w tych klasach w klasie abstrakcyjnej, które nie są zadeklarowane jako abstrakcyjne:

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;
    }
}

W końcu fabryka wygląda mniej więcej tak:

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;
    }
}

Odbiorca AbstractGridManager wywoła na nim metody i otrzymuje logikę zaimplementowaną w konkretnym descenderze (i częściowo w abstrakcyjnych metodach klasowych), nie wiedząc, co to jest konkretny dostał implementację. Jest to również znane jako inwersja sterowania lub iniekcji zależności.

 2
Author: Picrochole,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-09 06:46:33

Nie, Nie możemy utworzyć obiektu klasy abstrakcyjnej, ale utworzyć zmienną referencyjną klasy abstrakcyjnej. Zmienna odniesienia jest używana do odwoływania się do obiektów klas pochodnych (podklas klasy abstrakcyjnej)

Oto przykład, który ilustruje to pojęcie

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()); 
    } 
}

Tutaj widzimy, że nie możemy utworzyć obiektu typu Figure, ale możemy utworzyć zmienną referencyjną typu Figure. Tutaj stworzyliśmy zmienną referencyjną typu Figure I figure class reference zmienna jest używana do odwoływania się do obiektów klasy Rectangle i Triangle.

 1
Author: Ketan G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-09 08:40:02