(1) 추상 클래스 (Abstract Class) : 공통된 특성을 추출해서 만든 클래스
Q. 왜 추상클래스를 만들까?
> ex) 본사에서 메뉴만 정해주고 가격은 정해주지 x --> 각 매장에서 가격을 정해서 사용해라
---> 즉, 추상적으로 정의할 테니, 사용자가 꼭 '강제적'으로 overriding(재정의) 하라는 의미!!
ex) 어떤 메소드는 override하고, 어떤 메소드는 override를 하지 않을 경우, 본사에서 가격을 정하지 않았기 때문에 0원이 발생하는 경우가 존재한다. 따라서 모든 추상메소드를 override 해야 함!!!!
> 추상클래스를 상속 받은 실체 클래스의 공통된 필드와 메소드 이름을 통일할 목적으로 생성
= 여러 사람이 실체 클래스를 설계할 경우, 제각기 필드와 메소드 이름을 가질 수 있기 때문에 통일
> 실체 클래스 작성시 시간 절약
> 하위클래스에서 상위클래스의 메소드를 재정의 할 필요가 없을 때는 일반메소드 주로 사용
(ex) 식당에서 모든 사람들이 먹는 메뉴들)
> 하위클래스에서 상위클래스의 메소드를 각 상황에 맞게 재정의 할 필요가 있을 때 추상메소드 주로 사용
(ex) 식당에서 각각의 사람들이 먹는 메뉴들)
(2) 추상 메소드(abstract method)를 하나 이상 가진 클래스
* 추상 메소드란?
> method의 body(구현부,{중괄호})가 없는 method
--> 상속받는 자식 클래스에 기능을 위임하는 개념
> abstract keyword(modifier) 사용
> 추상 클래스 내부에는 일반 메소드 구현도 가능하다.
형식)
접근제어자 abstract ReturnType methodName ([args]); - 매개변수 생략 가능
ex)
public void a(); >> o - a라는 추상 메소드를 만들 것이다.
public void b() {} >> x - 아무 일도 하지 않는 일반 메소드
추상클래스 형식)
접근제어자 abstract class ClassName {
field
constructor
method
- 구현 method(){}
- abstract 추상 method();
}
**2. 추상클래스는 하위 클래스를 제어하기 위해 사용한다. (2,3번 함께 생각)
**3. 추상클래스는 자신의 생성자로 객체 생성이 불가능하고, 부모 클래스로만 사용된다.
>> 2+3 : 추상클래스는 하위클래스에 상속 후 사용 가능 --> 추상클래스를 상속받는 클래스는 '반.드.시' 추상메소드를 override해야 한다. (강제적으로!!!)
ex)
>> 다형성 : 하위 클래스를 참조하여 상위 클래스의 객체를 생성한다.
4. 추상클래스의 객체 생성 방법
a. 하위 클래스를 참조 (가장 일반적 방법 50%정도 사용)
b. 자신의 객체를 return하는 static method 이용
c. 외부클래스를 참조
d. 자신의 생성자 이용 (경우에 따라서 가능한 경우)
(3) 클래스 형변환
** 부모 타입으로 자식을 가리킬 수 있다. 이 경우 부모가 가지고 있는 필드 or 메소드만 사용이 가능하다.
Dohyung d1 = new Rect();
d1.calcArea();
d1.calcRound();
Q. 부모가 자식의 필드나 메소드를 사용하고 싶다면?? 클래스 형변환을 하면 OK~~~
Rect rect = (Rect) d1;
- Animal 추상클래스 만들기
public abstract class Animal {
public String kind;
public void breathe(){
System.out.println("숨을 쉰다");
}
public abstract void sound();//추상 메소드는 추상 클래스에서만 사용 가능
//동물들의 울음소리는 다 다르기 때문에 추상 메소드로 만들어주기
}
public class Dog extends Animal {
public Dog(){
this.kind = "포유류";
}
@Override
public void sound(){
System.out.println("멍멍");
};
}
public class Cat extends Animal {
public Cat(){
this.kind = "포유류";
}
@Override
public void sound(){
System.out.println("야옹");
};
}
public class AnimalExample {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
dog.sound();
cat.sound();
System.out.println("----------------");
Animal animal = null; // animal이라는 변수 생성
animal = new Dog(); //자식객체를 만들어서 부모 변수에 대입 (자동타입변환)
animal.sound(); // override한 자식 메소드 실행 : 멍멍
animal = new Cat();
animal.sound(); // override한 자식 메소드 실행 : 야옹
}
}
- Dohyung 추상클래스 만들기
public abstract class Dohyung { //Dohyung.java:1: error: Dohyung is not abstract and does not override abstract method calcRound() in Dohyung
//추상클래스로 만들기(강제성)
public abstract double calcArea(); //추상메소드로 만들기
public abstract double calcRound();
}
public class Rect extends Dohyung{
int width;
int height;
public Rect(){
this(4,3);
}
public Rect(int width, int height){
this.width = width;
this.height = height;
}
public double calcArea(){
return width * height;
}
public double calcRound(){
return (width + height) * 2;
}
void info(){
System.out.println("사각형입니다.");
}
}
public class Circle extends Dohyung {
int radius;
public Circle(){ //반지름 = 4
radius = 4;
}
public Circle(int radius){ //외부 값 입력
this.radius = radius;
}
public double calcArea(){
return Math.pow(radius,2)*Math.PI;//Math.pow(radius,2) : 제곱근, Math.PI : 파이값
}
public double calcRound(){
return 2*Math.PI*radius;
}
}
- 실행클래스
public class MatheMatics {
static void printDohyung(Rect rect) {
double area = rect.calcArea();
double round = rect.calcRound();
System.out.println("가로가 " + rect.width + "이고 세로가 " + rect.height + "인 사각형의 넓이는 " + area + "이고 둘레는 " + round + "입니다.");
}
static void printDohyung(Circle circle) {
double area = circle.calcArea();
double round = circle.calcRound();
System.out.println("반지름이 " + circle.radius + "인 원의 넓이는 " + area + "이고 둘레는 " + round + "입니다.");
}
public static void main(String[] args) {
//int area = 0;
//int round = 0;
//default 생성자를 이용한 넓이와 둘레를 구하시오.
Rect r1 = new Rect();
//가로가 4이고 세로가 3인 사각형의 넓이는 12이고 둘레는 14입니다.
/*
area = r1.calcArea();
round = r1.calcRound();
System.out.println("가로가 " + r1.width + "이고 세로가 " + r1.height +
"인 사각형의 넓이는 " + area + "이고 둘레는 " + round + "입니다.");
*/
printDohyung(r1);
//가로 7, 세로 5인 사각형의 넓이와 둘레를 구하시오.
Rect r2 = new Rect(7, 5);
//가로가 7이고 세로가 5인 사각형의 넓이는 35이고 둘레는 24입니다.
/*
area = r2.calcArea();
round = r2.calcRound();
System.out.println("가로가 " + r2.width + "이고 세로가 " + r2.height +
"인 사각형의 넓이는 " + area + "이고 둘레는 " + round + "입니다.");
*/
printDohyung(r2);
Circle c1 = new Circle();
printDohyung(c1);
Circle c2 = new Circle(6);
printDohyung(c2);
//Dohyung d1 = new Dohyung(); error 추상클래스는 자신의 생성자로 객체 생성 할 수 x
Dohyung d1 = new Rect(); // 추상클래스는 하위클래스를 참조해서 객체를 생성한다.
//d1.info();
//System.out.println("가로가 " + d1.width + "이고 세로가 " +
// d1.height + "인 사각형의 넓이는 " + d1.calcArea());
System.out.println("도형의 넓이는 " + d1.calcArea());
Rect r = (Rect) d1;
System.out.println("가로가 " + r.width + "이고 세로가 " + r.height + "인 사각형의 넓이는 " + r.calcArea());
Circle c = (Circle) d1;
System.out.println("반지름이 " + c.radius + "인 사각형의 넓이는 " + r.calcArea());
}
}
---------- run ----------
가로가 4이고 세로가 3인 사각형의 넓이는 12.0이고 둘레는 14.0입니다.
가로가 7이고 세로가 5인 사각형의 넓이는 35.0이고 둘레는 24.0입니다.
반지름이 4인 원의 넓이는 50.26548245743669이고 둘레는 25.132741228718345입니다.
반지름이 6인 원의 넓이는 113.09733552923255이고 둘레는 37.69911184307752입니다.
도형의 넓이는 12.0
가로가 4이고 세로가 3인 사각형의 넓이는 12.0
Exception in thread "main" java.lang.ClassCastException: Rect cannot be cast to Circle
at MatheMatics.main(MatheMatics.java:58)
1번 ------------> 2번 ----------------> 3번 순으로 생성
Heap |
Object (최상위클래스) |
Dohyung calcArea() calcRound() |
Rect info() |
Stack |
|
d1 |
r |
****
-Dohyung d1 = new Dohyung();
error? 추상클래스는 자신의 생성자로 객체 생성 할 수 x
-Dohyung d1 = new Rect(); // 추상클래스는 하위클래스를 참조해서 객체를 생성한다.
d1.info(); // error : 도형클래스에는 info가 없기 때문에 에러
-Rect r = (Rect) d1; //d1을 Rect로 변환하면 대입 가능하다.
-Circle c = (Circle) d1;
error ? Circle은 객체가 만들어지지 않았기 때문