[java] 자바의 추상 클래스

Java에서 “추상 클래스”란 무엇입니까?



답변

추상 클래스는 인스턴스화 할 수없는 클래스입니다. 추상 클래스는 인스턴스화 할 수 있는 상속 서브 클래스를 작성하여 사용됩니다 . 추상 클래스는 상속 서브 클래스에 대해 몇 가지 작업을 수행합니다.

  1. 상속 서브 클래스에서 사용할 수있는 메소드를 정의하십시오.
  2. 상속 서브 클래스가 구현해야하는 추상 메소드를 정의하십시오.
  3. 서브 클래스를 다른 모든 서브 클래스와 교환 할 수있는 공통 인터페이스를 제공하십시오.

예를 들면 다음과 같습니다.

abstract public class AbstractClass
{
    abstract public void abstractMethod();
    public void implementedMethod() { System.out.print("implementedMethod()"); }
    final public void finalMethod() { System.out.print("finalMethod()"); }
}

“abstractMethod ()”에는 메소드 본문이 없습니다. 이로 인해 다음을 수행 할 수 없습니다.

public class ImplementingClass extends AbstractClass
{
    // ERROR!
}

구현하는 메소드가 없습니다 abstractMethod()! 따라서 JVM이 다음과 같은 것을 얻을 때 수행해야 할 작업을 알 수있는 방법이 없습니다 new ImplementingClass().abstractMethod().

올바른 내용은 다음과 같습니다 ImplementingClass.

public class ImplementingClass extends AbstractClass
{
    public void abstractMethod() { System.out.print("abstractMethod()"); }
}

implementedMethod()또는 을 정의 할 필요는 없습니다 finalMethod(). 이미에 의해 정의되었습니다 AbstractClass.

또 다른 올바른 것이 ImplementingClass있습니다.

public class ImplementingClass extends AbstractClass
{
    public void abstractMethod() { System.out.print("abstractMethod()"); }
    public void implementedMethod() { System.out.print("Overridden!"); }
}

이 경우을 재정의했습니다 implementedMethod().

그러나 final키워드로 인해 다음이 불가능합니다.

public class ImplementingClass extends AbstractClass
{
    public void abstractMethod() { System.out.print("abstractMethod()"); }
    public void implementedMethod() { System.out.print("Overridden!"); }
    public void finalMethod() { System.out.print("ERROR!"); }
}

finalMethod()in AbstractClass구현이 최종 구현으로 표시되어 있기 때문에이 작업을 수행 할 수 없습니다 finalMethod(). 다른 구현은 절대 허용되지 않습니다.

이제 추상 클래스를 두 번 구현할 수도 있습니다 .

public class ImplementingClass extends AbstractClass
{
    public void abstractMethod() { System.out.print("abstractMethod()"); }
    public void implementedMethod() { System.out.print("Overridden!"); }
}

// In a separate file.
public class SecondImplementingClass extends AbstractClass
{
    public void abstractMethod() { System.out.print("second abstractMethod()"); }
}

이제 어딘가에 다른 방법을 쓸 수 있습니다.

public tryItOut()
{
    ImplementingClass a = new ImplementingClass();
    AbstractClass b = new ImplementingClass();

    a.abstractMethod();    // prints "abstractMethod()"
    a.implementedMethod(); // prints "Overridden!"     <-- same
    a.finalMethod();       // prints "finalMethod()"

    b.abstractMethod();    // prints "abstractMethod()"
    b.implementedMethod(); // prints "Overridden!"     <-- same
    b.finalMethod();       // prints "finalMethod()"

    SecondImplementingClass c = new SecondImplementingClass();
    AbstractClass d = new SecondImplementingClass();

    c.abstractMethod();    // prints "second abstractMethod()"
    c.implementedMethod(); // prints "implementedMethod()"
    c.finalMethod();       // prints "finalMethod()"

    d.abstractMethod();    // prints "second abstractMethod()"
    d.implementedMethod(); // prints "implementedMethod()"
    d.finalMethod();       // prints "finalMethod()"
}

우리가 선언에도 불구하고 있음을 공지 유형에서 표시 . 우리가 인스턴스화 된 객체가 실제로이었다 때문입니다 누구는 물론 오버라이드 (override)이다. (이것을 다형성이라고합니다.)bAbstractClass"Overriden!"ImplementingClassimplementedMethod()

특정 하위 클래스에 특정한 멤버에 액세스하려면 먼저 해당 하위 클래스로 캐스트해야합니다.

// Say ImplementingClass also contains uniqueMethod()
// To access it, we use a cast to tell the runtime which type the object is
AbstractClass b = new ImplementingClass();
((ImplementingClass)b).uniqueMethod();

마지막으로 다음을 수행 할 수 없습니다.

public class ImplementingClass extends AbstractClass, SomeOtherAbstractClass
{
    ... // implementation
}

한 번에 하나의 수업 만 연장 할 수 있습니다. 여러 클래스를 확장해야하는 경우 인터페이스 여야합니다. 당신은 이것을 할 수 있습니다 :

public class ImplementingClass extends AbstractClass implements InterfaceA, InterfaceB
{
    ... // implementation
}

인터페이스 예는 다음과 같습니다.

interface InterfaceA
{
    void interfaceMethod();
}

이것은 기본적으로 다음과 같습니다.

abstract public class InterfaceA
{
    abstract public void interfaceMethod();
}

유일한 차이점은 두 번째 방법은 컴파일러가 실제로 인터페이스라는 것을 알리지 않는다는 것입니다. 사람들이 인터페이스 만 구현하고 다른 인터페이스는 구현하지 않으려는 경우에 유용 할 수 있습니다. 그러나 일반적인 초급 규칙으로 추상 클래스에 추상 메소드 만있는 경우 인터페이스로 만들어야합니다.

다음은 불법입니다 :

interface InterfaceB
{
    void interfaceMethod() { System.out.print("ERROR!"); }
}

인터페이스에서 메소드를 구현할 수 없습니다. 이것은 두 개의 다른 인터페이스를 구현하면 해당 인터페이스의 다른 메소드가 충돌 할 수 없음을 의미합니다. 인터페이스의 모든 메소드는 추상이므로 메소드를 구현해야하며 메소드가 상속 트리에서 유일한 구현이므로 컴파일러는 메소드를 사용해야한다는 것을 알고 있습니다.


답변

Java 클래스는 다음과 같은 조건에서 요약됩니다.

1. 방법 중 하나 이상이 추상으로 표시됩니다.

public abstract void myMethod()

이 경우 컴파일러는 전체 클래스를 추상으로 표시하도록합니다.

2. 수업은 초록으로 표시됩니다.

abstract class MyClass

이미 말했듯이 : 추상 메소드가있는 경우 컴파일러는 전체 클래스를 추상으로 표시하도록 강제합니다. 그러나 추상 메서드가 없더라도 클래스를 추상으로 표시 할 수 있습니다.

일반적인 사용 :

추상 클래스의 일반적인 사용은 인터페이스와 유사한 클래스의 개요를 제공하는 것입니다. 그러나 인터페이스와 달리 이미 기능을 제공 할 수 있습니다. 즉, 클래스의 일부 부분이 구현되고 일부 부분은 메소드 선언으로 간략하게 설명됩니다. (“요약”)

추상 클래스는 인스턴스화 할 수 없지만 추상 클래스를 기반으로 구체적인 클래스를 생성 한 다음 인스턴스화 할 수 있습니다. 그렇게하려면 추상 클래스에서 상속하고 추상 메서드를 재정의해야합니다 (예 : 구현).


답변

abstract 키워드를 사용하여 선언 된 클래스 는로 알려져 있습니다 abstract class. 추상화는 데이터 구현 세부 사항을 숨기고 사용자에게 기능 만 표시하는 프로세스입니다. 추상화를 사용하면 객체가 수행하는 방식 대신 객체가 수행하는 작업에 집중할 수 있습니다.

추상 클래스의 주요 사항

  • 추상 클래스는 추상 메서드를 포함하거나 포함하지 않을 수 있습니다. 추상 클래스가 아닐 수 있습니다.

    추상 메소드는 다음과 같이 구현없이 (중괄호없이 세미콜론으로) 선언 된 메소드입니다.

    예 : abstract void moveTo(double deltaX, double deltaY);

  • 클래스에 추상 메소드가 하나 이상 있으면 해당 클래스는 추상적이어야합니다.

  • 추상 클래스가 인스턴스화되지 않을 수 있습니다 (Abstract 클래스의 객체를 생성 할 수 없음)

  • 추상 클래스를 사용하려면 다른 클래스에서 상속해야합니다. 모든 추상 메소드에 구현을 제공하십시오.

  • 추상 클래스를 상속하면 모든 추상 메소드에 구현을 제공해야합니다.

추상 클래스abstract 선언 선언하는 동안 클래스 앞에 키워드를
지정 하면 추상이됩니다. 아래 코드를 살펴보십시오.

abstract class AbstractDemo{ }

추상 메서드abstract 선언 선언하는 동안 메서드 앞에 키워드를
지정 하면 추상이됩니다. 아래 코드를 살펴보십시오.

abstract void moveTo();//no body

수업을 추상화해야하는 이유

객체 지향 도면 응용 프로그램에서 원, 사각형, 선, 베 지어 곡선 및 기타 여러 그래픽 객체를 그릴 수 있습니다. 이러한 객체에는 모두 특정 상태 (예 : 위치, 방향, 선 색상, 채우기 색상)와 동작 (예 :-: 이동 위치, 회전, 크기 조정, 그리기)이 공통적으로 있습니다. 이러한 상태와 동작 중 일부는 모든 그래픽 객체에서 동일합니다 (예 : 채우기 색상, 위치 및 이동 위치). 다른 것들은 다른 구현이 필요합니다 (예 : 크기 조정 또는 그리기). 모든 그래픽 객체는 스스로 그림을 그리거나 크기를 조정할 수 있어야하며, 작동 방식이 다릅니다.

이것은 추상 슈퍼 클래스에게 완벽한 상황입니다. 유사성을 활용 GraphicObject하고 다음 그림과 같이 동일한 추상 부모 개체 (예 : :)에서 상속하도록 모든 그래픽 개체를 선언 할 수 있습니다 .
여기에 이미지 설명을 입력하십시오

먼저, GraphicObject현재 위치 및 moveTo 메소드와 같은 모든 서브 클래스가 완전히 공유하는 멤버 변수 및 메소드를 제공하기 위해 추상 클래스를 선언합니다 . GraphicObject또한 모든 서브 클래스에 의해 구현되어야하지만 다른 방식으로 구현되어야하는 draw 또는 resize와 같은 추상 메소드를 선언했습니다. GraphicObject클래스는 다음과 같이 볼 수 있습니다 :

abstract class GraphicObject {

  void moveTo(int x, int y) {
    // Inside this method we have to change the position of the graphic 
    // object according to x,y     
    // This is the same in every GraphicObject. Then we can implement here. 
  }

  abstract void draw(); // But every GraphicObject drawing case is 
                        // unique, not common. Then we have to create that 
                        // case inside each class. Then create these    
                        // methods as abstract 
  abstract void resize();
}

서브 클래스에서의 추상 메소드 사용 and와 GraphicObject같은
각각의 추상이 아닌 서브 클래스 는 and 메소드에 대한 구현을 제공해야합니다 .CircleRectangledrawresize

class Circle extends GraphicObject {
  void draw() {
    //Add to some implementation here
  }
  void resize() {
    //Add to some implementation here   
  }
}
class Rectangle extends GraphicObject {
  void draw() {
    //Add to some implementation here
  }
  void resize() {
    //Add to some implementation here
  }
}

main메소드 내부에서 다음과 같은 모든 메소드를 호출 할 수 있습니다.

public static void main(String args[]){
   GraphicObject c = new Circle();
   c.draw();
   c.resize();
   c.moveTo(4,5);
}

Java에서 추상화를 달성하는 방법

자바에서 추상화를 얻는 두 가지 방법이 있습니다

  • 추상 클래스 (0 ~ 100 %)
  • 인터페이스 (100 %)

생성자, 데이터 멤버, 메소드 등이있는 추상 클래스

abstract class GraphicObject {

  GraphicObject (){
    System.out.println("GraphicObject  is created");
  }
  void moveTo(int y, int x) {
       System.out.println("Change position according to "+ x+ " and " + y);
  }
  abstract void draw();
}

class Circle extends GraphicObject {
  void draw() {
    System.out.println("Draw the Circle");
  }
}

class TestAbstract {
 public static void main(String args[]){

   GraphicObject  grObj = new Circle ();
   grObj.draw();
   grObj.moveTo(4,6);
 }
}

산출:

GraphicObject  is created
Draw the Circle
Change position according to 6 and 4

두 가지 규칙을 기억하십시오.

  • 클래스에 추상 메소드와 구체적인 메소드가 거의없는 경우 클래스로 선언하십시오 abstract.

  • 클래스에 추상 메소드 만있는 경우이를로 선언하십시오 interface.

참고 문헌 :


답변

인스턴스화 할 수없는 클래스이며 클래스를 구현하면 개요가있는 추상적 인 메소드를 구현해야합니다.


답변

간단히 말해서, 추상 클래스는 약간 더 많은 기능을 가진 인터페이스처럼 생각할 수 있습니다.

추상 클래스를위한 인터페이스도 인스턴스화 할 수 없습니다.

인터페이스에서 메소드 헤더를 정의하면 모든 구현자가 강제 로 모든 헤더 를 구현 해야 합니다. 추상 클래스에서 메소드 헤더를 정의 할 수도 있지만 여기서는 인터페이스의 차이점에 따라 메소드의 본문 (일반적으로 기본 구현)을 정의 할 수도 있습니다. 또한 다른 클래스가 추상 클래스를 확장 (구현하지 않고 따라서 자식 클래스 당 하나의 추상 클래스 만 가질 수 있음 ) 할 때 추상 메소드 를 지정하지 않는 한 추상 클래스의 모든 메소드를 강제로 구현하지는 않습니다 ( 이 경우 인터페이스와 같이 작동하며 메소드 본문을 정의 할 수 없습니다).

public abstract class MyAbstractClass{
  public abstract void DoSomething();
}

그렇지 않은 경우 추상 클래스의 일반 메서드의 경우 “상속자”는 기본 동작을 사용하거나 평소처럼 재정의 할 수 있습니다.

예:

public abstract class MyAbstractClass{

  public int CalculateCost(int amount){
     //do some default calculations
     //this can be overriden by subclasses if needed
  }

  //this MUST be implemented by subclasses
  public abstract void DoSomething();
}


답변

오라클 문서에서

추상 방법 및 클래스 :

추상 클래스는 추상으로 선언 된 클래스이며 추상 메소드를 포함하거나 포함하지 않을 수 있습니다.

추상 클래스는 인스턴스화 할 수 없지만 서브 클래스 화는 가능합니다

추상 메소드는 다음과 같이 구현없이 (중괄호없이 세미콜론으로) 선언 된 메소드입니다 .

abstract void moveTo(double deltaX, double deltaY);

클래스에 추상 메소드가 포함 된 경우 클래스 자체는 다음과 같이 추상으로 선언되어야합니다.

public abstract class GraphicObject {
   // declare fields
   // declare nonabstract methods
   abstract void draw();
}

추상 클래스가 서브 클래 싱 될 때, 서브 클래스는 일반적으로 부모 클래스의 모든 추상 메소드에 대한 구현을 제공합니다. 그러나 그렇지 않은 경우 서브 클래스도 abstract로 선언해야합니다. .

이후 abstract classesinterfaces 관련, SE 질문 아래를 보라 :

인터페이스와 추상 클래스의 차이점은 무엇입니까?

Interface와 Abstract 클래스의 차이점을 어떻게 설명해야합니까?


답변

여기에 답을 얻으십시오.

자바의 추상 클래스와 인터페이스

추상 클래스가 최종 메소드를 가질 수 있습니까?

BTW-최근 질문 한 내용입니다. 명성을 쌓기위한 새로운 질문에 대해 생각해보십시오.

편집하다:

이 포스터와 참조 된 질문의 이름은 같거나 최소한 비슷한 이름이지만 user-id는 항상 다릅니다. 따라서 기술적 인 문제가 있습니다. keyur가 다시 로그인하는 데 문제가 있고 그의 질문에 대한 답을 찾는 데 어려움이 있거나 SO 커뮤니티를 즐겁게하는 일종의 게임입니다.)