source

추상 수업을 인스턴스화할 수 있습니까?

factcode 2022. 7. 21. 23:32
반응형

추상 수업을 인스턴스화할 수 있습니까?

인터뷰 중에 "추상 수업을 인스턴스화할 수 있을까요?"라는 질문을 받았습니다.

'안 돼, 안 돼'라고 대답했어요.그런데 면접관이 "잘못했어, 할 수 있어"라고 말했어요.

나는 이것에 대해 조금 논쟁했다.그리고 나서 그는 나에게 이것을 집에서 직접 해보라고 말했다.

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

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

여기에서는 제 수업의 인스턴스와 추상 수업의 호출 방법을 만들고 있습니다.누가 이걸 설명해 줄 수 있나요?제가 면접을 보는 동안 정말 틀렸나요?

여기, 나는 내 수업의 예를 만들고 있다.

아니요, 여기서 추상 클래스의 인스턴스를 만들지 않습니다.오히려 추상 클래스의 익명 하위 클래스의 인스턴스를 만듭니다.그런 다음 하위 클래스 개체를 가리키는 추상 클래스 참조에서 메서드를 호출합니다.

이 동작은 JLS(섹션 번호15.9.1)에 명확하게 기재되어 있습니다.

클래스 인스턴스 생성 식이 클래스 본문으로 끝나는 경우 인스턴스화되는 클래스는 익명 클래스입니다.그 후, 다음과 같이 입력합니다.

  • T가 클래스를 나타내는 경우 T에 의해 명명된 클래스의 익명 직접 서브클래스가 선언됩니다.T로 표시된 클래스가 최종 클래스일 경우 컴파일 시간 오류입니다.
  • T가 인터페이스를 나타내는 경우 T에 의해 명명된 인터페이스를 구현하는 객체의 익명 직접 서브클래스가 선언됩니다.
  • 어느 경우든 서브클래스의 본문은 클래스 인스턴스 생성 식에서 지정된 ClassBody입니다.
  • 인스턴스화되는 클래스는 익명 서브클래스입니다.

강조해 주세요.

또한 JLS - 섹션 # 12.5에서 객체 생성 프로세스에 대해 읽을 수 있습니다.여기서 한 가지 말을 인용하겠습니다.-

새로운 클래스 인스턴스가 생성될 때마다 클래스 유형으로 선언된 모든 인스턴스 변수 및 클래스 유형의 각 슈퍼클래스에서 선언된 모든 인스턴스 변수(숨겨질 수 있는 모든 인스턴스 변수 포함)를 위한 공간이 해당 클래스 인스턴스에 할당됩니다.

결과적으로 새로 생성된 개체에 대한 참조가 반환되기 직전에 지정된 생성자는 다음 절차를 사용하여 새 개체를 초기화하도록 처리됩니다.

자세한 절차는 제가 제공한 링크에서 보실 수 있습니다.


인스턴스화된 클래스가 사실상 Anonymous SubClass임을 확인하려면 두 클래스를 모두 컴파일해야 합니다.이러한 클래스를 2개의 다른 파일에 격납한다고 합니다.

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

이제 두 소스 파일을 모두 컴파일합니다.

javac My.java Poly.java

이제 소스 코드를 컴파일한 디렉토리에 다음 클래스 파일이 표시됩니다.

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

를 참조해 주세요.Poly$1.class아래 코드를 사용하여 인스턴스화한 익명 서브클래스에 대응하는 컴파일러에 의해 작성된 클래스 파일입니다.

new My() {};

즉, 인스턴스화된 다른 클래스가 있는 것이 분명합니다.단지, 그 클래스는 컴파일러에 의한 컴파일이 끝난 후에만 이름이 붙여집니다.

일반적으로 클래스의 모든 익명 서브클래스의 이름은 다음과 같습니다.

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

이 숫자는 해당 익명 클래스가 둘러싸인 클래스에 나타나는 순서를 나타냅니다.

의 명령어는 어나니머스 합니다.이 클래스는 어나니머스 내부 내부 클래스는 어나니머스 내부 클래스입니다.이 내부 클래스는 다음 명령어의 서브 클래스입니다.my 수업자체를 하는 것과 엄밀하게 인 서브클래스의됩니다.OTOH, 모든 서브클래스 인스턴스는 모든 슈퍼클래스와 인터페이스의 인스턴스이기 때문에 대부분의 추상 클래스는 실제로 구체적인 서브클래스 중 하나를 인스턴스화함으로써 인스턴스화됩니다.

만약 면접관이 설명 없이 "틀렸다!"라고만 말하고, 독특한 반례 사례로 이 예를 들었다면, 그는 자신이 무슨 말을 하는지 모르는 것 같습니다.

= my() {};한 사물 가 아니라 것을 과 같습니다.이것은 다음과 같아야 합니다.= my()추상 클래스는 인스턴스화할 수 없습니다.

관찰할 수 있는 것은 다음과 같습니다.

  1. ★★★★poly를 확장하다my★★★★★★★★★★★★...
  2. 집집결 과떻 ?? ????의 파일: 3개의 파일:my.class,poly.class ★★★★★★★★★★★★★★★★★」poly$1.class
  3. 이와 같은 추상 클래스를 인스턴스화할 수 있다면 인터페이스도 인스턴스화할 수 있습니다.이상한...


추상 수업을 인스턴스화할 수 있습니까?

아니, 우린 못해.우리가 할 수 있는 일은 익명 클래스(세 번째 파일)를 만들고 인스턴스화하는 것입니다.


슈퍼클래스의 인스턴스화는 어떨까요?

추상 슈퍼클래스는 우리가 인스턴스화한 것이 아니라 자바에 의해 인스턴스화됩니다.

EDIT: 테스트를 의뢰합니다.

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

}

출력은 다음과 같습니다.

false
class my$1
class my$2

한 줄로 간단하게 대답할 수 있습니다.

아니요, 추상 클래스를 인스턴스화할 수 없습니다.

하지만 면접관이 아직 동의하지 않으시면 말씀하시면 됩니다.

할 수 있는 건 익명 클래스를 만드는 것뿐입니다.

또한 Anonymous 클래스에 따르면 클래스는 동일한 장소/회선에서 선언인스턴스화됩니다.

그래서 면접관은 당신의 신뢰수준과 OOP에 대해 얼마나 알고 있는지 확인하는 데 관심이 있을 수 있습니다.

기술적인 부분은 다른 답변에서 잘 다루어져 있으며, 주로 다음과 같은 내용으로 끝납니다.
틀렸어, 그는 아무것도 모르기 때문에 SO에 가입해서 모든 것을 해결하도록 요청했습니다."

이 질문은 스트레스 질문일 수 있으며, 많은 면접관이 당신을 더 잘 알 수 있는 중요한 도구이며, 어렵고 특이한 상황에 어떻게 반응하는지 알려드립니다.당신에게 잘못된 코드를 알려줌으로써, 그는 아마 당신이 반론을 제기하는지 보고 싶어 했을 겁니다.이런 상황에서 선배들에게 맞설 자신이 있는지 알아보는 것.

추신: 이유는 모르겠지만 면접관이 이 글을 읽었다는 느낌이 듭니다.

추상 클래스는 인스턴스화할 수 없지만 하위 클래스는 지정할 수 있습니다.이 링크 참조

가장 좋은 예는

Calender 클래스는 추상적인 메서드 getInstance()가지고 있습니다만,Calendar calc=Calendar.getInstance();

calc는 GregorianCalendar 클래스의 인스턴스를 "GregorianCalendar extended Calendar"로 나타냅니다.

Infact Annamymous inner type을 사용하면 추상 클래스의 no-name 하위 클래스와 이 클래스의 인스턴스를 만들있습니다.

기술적인 답변

추상 클래스는 인스턴스화할 수 없습니다. 이는 정의 및 설계에 의한 것입니다.

JLS의 제8장.클래스:

명명된 클래스는 추상(8 8.1.1.1)으로 선언될 수 있으며, 완전히 구현되지 않은 경우 추상이라고 선언해야 합니다. 이러한 클래스는 인스턴스화할 수 없지만 하위 클래스에 의해 확장될 수 있습니다.

Classes.newInstance()의 JSE 6 Java doc에서 다음을 수행합니다.

인스턴스화예외 - 이 클래스가 추상 클래스, 인터페이스, 배열 클래스, 원시 유형 또는 보이드를 나타내거나 클래스에 null 생성자가 없거나 다른 이유로 인스턴스화에 실패한 경우.

물론 추상 클래스의 구체적인 하위 클래스(어나니머스 하위 클래스 포함)를 인스턴스화하고 추상 유형에 대한 객체 참조의 형식 캐스트를 수행할 수 있습니다.

다른 시각 - 팀 플레이와 소셜 인텔리전스:

이러한 기술적 오해는 복잡한 기술과 법률적 사양을 다룰 때 현실에서 자주 발생합니다.

여기서는 "기술적 기술"보다 "인력 기술"이 더 중요할 수 있습니다.만약 경쟁적이고 공격적으로 여러분의 주장을 증명하려고 한다면, 이론적으로 여러분이 옳을 수 있지만, 여러분은 또한 싸울 때, "얼굴"을 손상시키는 것, 가치보다 적을 만드는 것에 더 큰 피해를 줄 수도 있습니다.차이점을 해결할 때 화해와 이해를 하세요."둘 다 옳을 수도 있지만" 용어의 의미가 약간 다른지 누가 알겠어요?

누가 알겠는가?-그럴 것 같지는 않지만, 면접관이 당신을 도전적인 상황에 빠뜨리고 당신이 감정적으로나 사회적으로 어떻게 행동하는지 보기 위해 의도적으로 작은 갈등/오해를 소개했을 가능성이 있다.동료에게 친절하고 건설적인 태도를 보이고, 선배의 조언을 따르고, 면접 후에 이메일이나 전화를 통해 문제나 오해를 해결합니다.의욕적이고 디테일을 중시한다는 것을 알 수 있습니다.

abstract class모두가 대답한 것처럼 인스턴스화할 수 없습니다.

클래스를 새 ).EnclosedClassName$n서 ''는n★★★★★★★★★★★★★★★★★★★★★★★★★★」

따라서 이 Java 클래스를 디컴파일하면 다음과 같은 코드를 찾을 수 있습니다.

마이클래스

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

poly$1.class('syslog 클래스'의 생성된 클래스)

class poly$1 extends my 
{
} 

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

아니요, 추상 클래스는 인스턴스화할 수 없습니다.익명의 클래스만 인스턴스화 합니다.추상 수업에서 우리는 추상적인 방법을 선언하고 구체적인 방법만을 정의한다.

클래스를 확장한다고 해서 클래스를 인스턴스화하는 것은 아닙니다.실제로 이 경우 서브클래스의 인스턴스를 만들고 있습니다.

나는 추상 수업이 시작을 허용하지 않는다고 확신한다.그래서 저는 아니라고 생각합니다. 추상적인 수업은 인스턴스화할 수 없습니다.단, 연장/상속할 수 있습니다.

추상 클래스는 직접 인스턴스화할 수 없습니다.그러나 간접적으로 클래스의 인스턴스(원래 추상 클래스의 인스턴스가 아님)를 얻을 수 없는 것은 아닙니다.즉, 원래 추상 클래스는 인스턴스화할 수 없지만 다음과 같이 할 수 있습니다.

  1. 빈 클래스 만들기
  2. 추상 클래스에서 상속
  3. 데비드 클래스의 인스턴스화

따라서 파생 클래스 인스턴스를 통해 추상 클래스의 모든 메서드 및 속성에 액세스할 수 있습니다.

추상 클래스에 대해서

  • 추상 클래스의 개체를 만들 수 없습니다.
  • 변수를 생성할 수 있습니다(데이터 유형처럼 동작할 수 있음).
  • 자녀가 부모의 추상적 방법 중 적어도 하나를 재정의할 수 없는 경우 자녀도 추상화됩니다.
  • 추상수업은 자녀수업 없이는 무용지물이다.

추상 클래스의 목적은 기본처럼 행동하는 것입니다.상속 계층에서는 맨 위에 추상 클래스가 표시됩니다.

다음과 같이 말할 수 있습니다.
추상 클래스는 인스턴스화할 수 없지만new키워드를 지정하여 어나니머스 클래스인스턴스를 만듭니다.{}추상 클래스의 마지막에 구현 본문으로 사용됩니다.

추상적인 수업을 인스턴스화하는 것은 불가능하다.여러분이 정말로 할 수 있는 것은 추상적인 클래스에서 몇 가지 일반적인 메서드를 구현하고 다른 메서드는 구현되지 않은 상태로 두는 것입니다(추상적인 것으로 선언함). 그리고 구체적인 내림차순자는 그들의 요구에 따라 그것들을 구현합니다.그런 다음 이 추상 클래스의 인스턴스(실제로 구현자)를 반환하는 팩토리를 만들 수 있습니다.그 후 공장에서 어떤 구현자를 선택할지 결정합니다.이를 공장 설계 패턴이라고 합니다.

   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
    }

구체적인 구현자는 추상이라고 선언된 메서드를 구현하기만 하면 되지만 추상 클래스 내의 이러한 클래스에서 구현된 로직에는 액세스할 수 있습니다.이러한 로직은 추상이라고 선언되지 않습니다.

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

마지막으로 공장은 다음과 같습니다.

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

AbstractGridManager의 수신자는 그에게 메서드를 호출하여 구체적인 내림차순서(및 부분적으로 추상 클래스 메서드)에서 구현된 로직을 얻을 수 있습니다.이를 제어 반전 또는 의존성 주입이라고도 합니다.

아니요, 추상 클래스의 개체를 만들 수는 없지만 추상 클래스의 참조 변수를 만들 수는 없습니다.참조 변수는 파생 클래스의 개체를 참조하는 데 사용됩니다(Abstract 클래스의 하위 클래스).

다음은 이 개념을 설명하는 예입니다.

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

여기서는 그림 유형의 개체를 만들 수 없지만 그림 유형의 참조 변수를 만들 수 있습니다.여기서는 그림 유형의 참조 변수를 만들었습니다. 그림 클래스 참조 변수는 클래스 직사각형 및 삼각형의 개체를 참조하는 데 사용됩니다.

사실 추상 클래스의 개체를 직접 만들 수는 없습니다.작성하는 것은 추상 콜의 참조 변수입니다.참조 변수는 추상 클래스를 상속하는 클래스의 개체, 즉 추상 클래스의 하위 클래스를 참조하는 데 사용됩니다.

언급URL : https://stackoverflow.com/questions/13670991/can-we-instantiate-an-abstract-class

반응형