JAVA/수업 복습

자바 공부기록 52 - Abstract 추상 클래스

본이qq 2022. 5. 12. 10:29

●추상클래스
-상속을 통한 다형성(부모클래스를 상속받아 여러형태의 자식클래스를 생성 & 활용 & type casting)을 
구현함에 있어서 강제성을 부여하기 위한 클래스
-일반적인 상속의 문제점 : 강제성의 부재
-상속을 통해 다형성(부모클래스를 상속받아 여러 형태의 자식 클래스를 생성하고 활용함)을
  구현하고자 하여도, 하위클래스에서 메소드 오버라이딩을 구현하지 않으면 다형성을 완벽히
  구현할 수 없습니다. 
-이때, 오버라이딩을 구현하지 않는것이 문법상 문제가 없다는 점을 강제성의 부재라고 합니다

 

 

 

 

●추상 클래스 (Abstract Class)
-상속을 통한 다형성의 구현(메서드 오버라이드)에 강제성을 부여하기 위한 클래스 
-추상메소드를 포함한 클래스 : 추상 메서드를 하나이상 포함하면 추상클래스라고 부릅니다
-추상메서드 : 메소드의 원형만 존재하고 실제 내용이 없는 메소드입니다

 

추상메소드의 작성방법
-접근지정자 abstract 리턴값의타입 메소드명( 매개변수 );
-추상 클래스는 일반 클래스와 동일하게 일반 멤버변수 일반 메소드, 생성자 등을 포함할 수 있습니다.
-단, 추상 메소드를 포함할 수 있는 특징이 추가된 클래스입니다.
-추상클래스는 상속을 통한 다형성 구현을 위해서 생성됩니다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
abstract class AbstractAnimal{    // 추상클래스
    private int age=5;
    public void addAge() {
        age++;
    }
    public abstract void crying();    // 추상메서드
}
 
class DogA extends AbstractAnimal{
    @Override
    public void crying() {
        System.out.println("멍~멍~");        
    }
}
class CatA extends AbstractAnimal{
    @Override
    public void crying() {  
        System.out.println("야옹~");    
    }
}
 
public class Abstract02 {
 
    public static void main(String[] args) {
        DogA d = new DogA();
        d.crying();
        CatA c = new CatA();
        c.crying();
cs

 

 

※추상클래스는 상속전용으로 만들어 지므로, 아래와 같이 단독으로 객체 생성을 하지 못합니다
 AbstractAnimal a = new AbstractAnimal(); // 에러
 추상메서드를 포함하고 있는 클래스는, 말그데로 완전하지 않은 클래스상태라는 뜻입니다
 따라서 자체적인 객체 생성이 되지 않습니다

 추상클래스로 추상클래스만의 객체를 만들수는 없지만
 추상클래스(부모)의 레퍼런스 변수로, 자식클래스의 인스턴스 주소는 저장할 수 있습니다
 AbstractAnimal a = new AbstractAnimal(); X
 AbstractAnimal b = new DogA();  O
 AbstractAnimal c = new CatA();  O

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 
public class Abstract02 {
 
    public static void main(String[] args) {
        AbstractAnimal dog = new DogA();        
        AbstractAnimal cat = new CatA();
        dog.crying();
        cat.crying();
        dog.addAge();
        cat.addAge();
        
        increamentAge(d);
        increamentAge(c);
}
    // 자식 클래스의 인스턴스를 전달인수로 보내면, 함수의 매개변수인 부모 레퍼런스가 받아서 사용할
    // 수 있습니다.
    public static void increamentAge( AbstractAnimal animal ) {
        animal.addAge();
    }
 
}
cs

 

 

●추상 클래스의 단점
-추상 메소드 구현의 강제성이 아래의 경우 단점이 될 수 있습니다
-추상 메소드의 갯수가 많으면 상속에 부담을 주게 됩니다.
-자식 클래스에서 사용하지 않을 추상 메소드라도, 객체 생성을 위해 반드시 구현해야 
  하는 문제점이 있습니다.

1
2
3
4
5
6
7
8
9
abstract class AbstractA{
    public abstract void test1();
    public abstract void test2();
    public abstract void test3();
    public abstract void test4();
    public abstract void test5();
    public abstract void test6();
    public abstract void test7();
}
cs

 

 

->AbstractA 클래스를 상속 받은 클래스는 필요없는 메서드가 있어도, 추상매서드를 모두 오버라이드(구현)해야   합니다

 

->모든 추상매서드가 구현(오버라이드)된 AbstractA_Adapter 클래스를 생성하고,
   이 클래스를 상속받아 사용하면 필요없는 매서드를 강제로 구현(오버라이드)하지 않고 필요한 것만 
   구현하여 사용할 수 있습니다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
abstract class AbstractA{
    public abstract void test1();
    public abstract void test2();
    public abstract void test3();
    public abstract void test4();
    public abstract void test5();
    public abstract void test6();
    public abstract void test7();
}
class AbstractA_Adapter extends AbstractA {
    @Override
    public void test1() { }
    @Override
    public void test2() { }
    @Override
    public void test3() { }
    @Override
    public void test4() { }
    @Override
    public void test5() { }
    @Override
    public void test6() { }
    @Override
    public void test7() { }
}
class AbstractA_Sub2 extends AbstractA_Adapter {
    public void test1() {
        System.out.println("test1 오버라이딩~!");    
    }
}
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package days31;
 
 
abstract class AbstractA{
    public abstract void test1();
    public abstract void test2();
    public abstract void test3();
    public abstract void test4();
    public abstract void test5();
    public abstract void test6();
    public abstract void test7();
}
 
class AbstractA_Adapter extends AbstractA {
    @Override
    public void test1() { }
    @Override
    public void test2() { }
    @Override
    public void test3() { }
    @Override
    public void test4() { }
    @Override
    public void test5() { }
    @Override
    public void test6() { }
    @Override
    public void test7() { }
}
class AbstractA_Sub2 extends AbstractA_Adapter {
    public void test1() {
        System.out.println("test1 오버라이딩~!");    
    }
}
 
public class Abstract03 {
 
    public static void main(String[] args) {
        // 어댑터 클래스를 상속받은 클래스도 추상클래스의 자식(손자)클래스가 됩니다.
        AbstractA obj = new AbstractA_Sub2();
        obj.test1();
        // 할아버지 손자간 다형성을 구현하여
        // 물려주고 오버라이딩된 메서드를 할아버지 레퍼런스가 사용할 수 있습니다.
        
        // 함수의 전달인수로 손자인스턴스 주소를 보내고, 함수의 매개변수로 할아버지 레퍼런스사용이
        // 아래와 같이 가능합니다
        test( obj );
 
    }
    public static void test( AbstractA object1 ) {
        
    }
 
}
 
cs