안녕! Java의 추상 클래스 에 대해 이야기해 봅시다 .Java의 추상 클래스에 대한 구체적인 예 - 1

클래스를 "추상"이라고 부르는 이유는 무엇입니까?

당신은 아마 추상화가 무엇인지 기억할 것입니다 — 우리는 이전에 그것에 대해 논의했습니다 :) 잊어버렸더라도 걱정하지 마세요. 클래스를 설계하고 개체를 만들 때 엔터티의 기본 속성만 나타내고 보조 속성은 버려야 한다는 것이 OOP 원칙임을 기억하십시오 . SchoolTeacher예를 들어 수업을 설계하는 경우 키는 교사의 필수 속성이 아닐 수 있습니다. 실제로 이 특성은 교사에게 중요하지 않습니다. BasketballPlayer그러나 클래스를 생성하는 경우 키가 가장 중요한 특성 중 하나가 됩니다. 음, 추상 클래스미래 클래스 그룹에 대한 가장 추상적이고 "거친 공작물"입니다. 공작물을 직접 사용할 수 없습니다. 너무 "거칩니다". 그러나 미래의 클래스(추상 클래스의 후손)가 갖게 될 특정 특성 상태와 동작을 정의합니다.

Java의 추상 클래스 예

자동차에 대한 간단한 예를 고려하십시오.

public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;
  
   public abstract void gas();

   public abstract void brake();

   public String getModel() {
       return model;
   }

   public void setModel(String model) {
       this.model = model;
   }

   public String getColor() {
       return color;
   }

   public void setColor(String color) {
       this.color = color;
   }

   public int getMaxSpeed() {
       return maxSpeed;
   }

   public void setMaxSpeed(int maxSpeed) {
       this.maxSpeed = maxSpeed;
   }
}
이것이 가장 단순한 추상 클래스의 모습입니다. 보시다시피 특별한 것은 없습니다 :) 왜 이것이 필요한가요? 첫째, 우리가 필요로 하는 개체인 자동차에 대한 가장 추상적인 설명을 제공합니다. 추상 키워드 는 여기서 무언가를 의미합니다. 현실 세계에서 "단지 자동차"와 같은 것은 없습니다. 트럭, 경주용 자동차, 세단, 쿠페 및 SUV가 있습니다. 추상 클래스는 나중에 특정 자동차 클래스를 만드는 데 사용할 "청사진"일 뿐입니다.

public class Sedan extends Car {
  
   @Override
   public void gas() {
       System.out.println("The sedan is accelerating!");
   }

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }
  
}
여러 면에서 이것은 상속에 대한 수업에서 이야기한 것과 유사합니다. 이 경우 Car에만 메소드가 추상이 아닌 클래스가 있습니다. 그러나 이러한 솔루션에는 추상 클래스에서 수정되는 몇 가지 단점이 있습니다. 무엇보다도 추상 클래스의 인스턴스를 만들 수 없습니다.

public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Error! The Car class is abstract!
   }
}
Java 작성자는 의도적으로 이 "기능"을 만들었습니다. 다시 한 번 기억하세요. 추상 클래스는 미래의 "일반" 클래스를 위한 청사진일 뿐입니다 . 청사진 사본이 필요하지 않습니까? 마찬가지로 추상 클래스의 인스턴스를 만들 필요가 없습니다. :) 클래스가 Car추상 클래스가 아닌 경우 인스턴스를 쉽게 만들 수 있습니다.

public class Car {

   private String model;
   private String color;
   private int maxSpeed;
  
   public void go() {
       // ...some logic
   }

   public  void brake() {
       // ...some logic
   }
}


public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // This is okay. The car is created.
   }
}
현재 우리 프로그램에는 이해할 수 없는 자동차가 있습니다. 트럭도 아니고 경주용 자동차도 아니고 세단도 아닌데 그게 뭔지는 정말 불명. 그것은 현실에 존재하지 않는 "단지 자동차"입니다. 동일한 예가 동물에 대해 주어질 수 있습니다. 프로그램에 Animal객체(" 동물만 ")가 있다고 상상해 보십시오. 어떤 종류인지, 어떤 과에 속하는지, 어떤 특징을 가지고 있는지는 명확하지 않다. 프로그램에서 하나를 보는 것은 이상할 것입니다. 자연에는 "단순한 동물"이 없습니다. 개, 고양이, 여우, 두더지 등만 있습니다. 추상 클래스는 " 단지 객체 " 에서 우리를 구합니다 . 기본 상태와 동작을 제공합니다. 예를 들어 모든 차량에는 모델 , 색상최고 속도가 있어야 합니다.그리고 그들은 또한 가스브레이크를 적용할 수 있어야 합니다 . 그게 다야. 나중에 필요한 클래스를 디자인하는 데 사용할 일반적인 추상 청사진입니다. 참고: 추상 클래스의 두 메서드도 추상 이므로 구현이 전혀 없습니다. 이유는 동일합니다. 추상 클래스는 "단지 자동차"에 대한 "기본 동작"을 생성하지 않습니다. 그들은 단지 모든 자동차가 할 수 있어야 하는 것을 나타냅니다. 즉, 기본 동작이 필요한 경우 추상 클래스에서 메서드를 구현할 수 있습니다. Java는 다음을 금지하지 않습니다.

public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       System.out.println("Accelerating!");
   }

   public abstract void brake();
  
   // Getters and setters
}


public class Sedan extends Car {

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }

}

public class Main {

   public static void main(String[] args) {

       Sedan sedan = new Sedan();
       sedan.gas();
   }
}
콘솔 출력:
Accelerating!
보시다시피 추상 클래스에 하나의 메서드를 구현했지만 다른 하나는 구현하지 않았습니다. 결과적으로 Sedan클래스의 동작은 두 부분으로 나뉩니다. 메소드를 호출하면 gas()동작이 추상 상위 클래스에서 "풀업"되고 클래스 에서 메소드를 Car구현합니다 . 매우 편리하고 유연합니다. 하지만 지금 우리 수업은 그렇게 추상적이지 않죠 ? 결국 실제로 절반의 방법을 구현했습니다. 사실은 — 그리고 이것은 매우 중요한 특징입니다 — 메서드 중 하나라도 추상이면 클래스는 추상입니다.brake()Sedan. 둘 중 한 가지 방법이든, 천 가지 중 하나이든 상관 없습니다. 우리는 모든 메소드를 구현하여 추상화를 남기지 않을 수도 있습니다. 결과는 추상 메서드가 없는 추상 클래스입니다. 이것은 원칙적으로 가능합니다. — 컴파일러는 어떠한 오류도 생성하지 않습니다 — 그러나 추상이라는 단어의 의미를 박탈하기 때문에 이렇게 하지 않는 것이 좋습니다. 당신의 동료 프로그래머들도 이것을 보고 매우 놀랄 것입니다. 즉, 메소드가 추상으로 표시되면 각 자손 클래스는 이를 구현하거나 추상으로 선언해야 합니다. 그렇지 않으면 컴파일러에서 오류가 발생합니다.. 물론 각 클래스는 하나의 추상 클래스만 상속할 수 있으므로 상속 측면에서 추상 클래스와 일반 클래스의 차이는 없습니다. 추상 클래스를 상속하든 일반 클래스를 상속하든 상관 없습니다. 부모 클래스는 하나만 있을 수 있습니다.

Java에 다중 클래스 상속이 없는 이유

우리는 이미 Java에 다중 상속이 없다고 말했지만 실제로 그 이유를 조사하지는 않았습니다. 지금 해보자. 사실 Java에 다중 상속이 있는 경우 하위 클래스는 선택할 동작을 결정할 수 없습니다. Toaster다음과 같은 두 개의 클래스가 있다고 가정해 보겠습니다 NuclearBomb.

public class Toaster {
  
  
 public void on() {

       System.out.println("The toaster is on. We're toasting!");
   }
  
   public void off() {

       System.out.println("The toaster is off!");
   }
}


public class NuclearBomb {

   public void on() {

       System.out.println("Boom!");
   }
}
보시다시피 두 클래스 모두 on()메서드가 있습니다. 토스터의 경우 방법은 토스트를 만들기 시작하지만 핵폭탄의 경우 폭발을 일으킵니다. 어-오 :/ 이제 그 사이에 무언가를 만들기로 결정했다고 상상해 보세요(이유는 묻지 마세요!). 수업은 다음과 같습니다. MysteriousDevice! 물론 이 코드는 작동하지 않습니다. "무엇이 있었는지"의 예로서 간단히 제시합니다.

public class MysteriousDevice extends Toster, NuclearBomb {

   public static void main(String[] args) {
      
       MysteriousDevice mysteriousDevice = new MysteriousDevice();
       mysteriousDevice.on(); // And what should happen here? Will we get toast or a nuclear apocalypse?
   }
}
우리가 가진 것을 보자. 신비한 장치는 Toaster와 NuclearBomb에서 동시에 파생됩니다. 둘 다 방법이 있습니다 on(). 결과적으로 객체를 호출하는 경우 어떤 구현을 실행해야 하는지 명확하지 on()않습니다 MysteriousDevice. 물체는 이해하지 못할 것입니다. 무엇보다도 NuclearBomb에는 off()방법이 없으므로 정확하게 추측하지 않으면 장치를 끌 수 없습니다. Java의 추상 클래스에 대한 구체적인 예 - 2어떤 동작을 실행해야 하는지 명확하지 않을 때 이러한 "오해"는 Java 작성자가 다중 상속을 거부한 정확한 이유입니다. 즉, Java 클래스가 많은 인터페이스를 구현할 수 있다는 것을 알게 될 것입니다.