프로그래밍/Java

자바(JAVA) 인터페이스와 추상클래스의 설명과 예제

abfc 2016. 9. 30.
반응형





추상메서드

정의 : 내용이 없는 메서드, 구현(정의)는 하지 않고 선언만 한 메서드

목적 : 메서드의 내용이 너무 일반적인 내용이라 부모 클래스에서 구체화하여 정의할 필요가 없을 경우, 추상메서드로 선언만하고 상속받은 자식 클래스에서 재정의하도록 할 때 사용


추상클래스(abstract class)

정의 : - 한 개 이상의 추상메서드를 가지는 클래스

   - 일반적인 클래스는 세부적이고, 구체적 ex) 고양이과, 개과

   - 반면 추상클래스는 일반클래스에 비해 구체적이지 않고 추상적 ex) 고양이, 사자, 강아지

목적 : 추상메서드는 선언만되고 구현이 되지 않은 불완전한 메서드이므로 객체로 생성되어서는 안됩니다. 

   이런 클래스(추상메서드가 포함된 클래스)는 추상클래스로 선언하여 객체 생성을 금지시킵니다.


추상클래스는 반드시 하나 이상의 추상메서드를 가지며, 객체를 생성할 수 없습니다. 하지만 슈퍼클래스로 사용할 수는 있으며 추상메서드를 사용하기 위해서는 반드지 해당 메서드를 재정의 해야만 합니다.





추상클래스 또는 추상메서드를 선언하기 위해서는 이름 앞에 abstract를 추가하면 됩니다.


추상클래스 형식

1
2
3
abstract class 클래스명{
    추성메서드();
}



추상메서드 형식

1
2
3
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
29
public class AbstractTest {
    public static void main(String[] args) {
        FirstCat fc = new FirstCat();
        SecondCat sc = new SecondCat();
        
        fc.call();
        sc.call();
    }
}//AbstractTest
 
abstract class Cat{ // 추상 메서드를 포함하므로 추상클래스로 선언
    abstract void call(); // 추상 메서드 선언(구현x)
    void call2(){
        System.out.println("일반 메서드");
    }
}
 
//Cat 추상클래스를 상속한 클래스들
class FirstCat extends Cat{
    void call(){ //추상메서드는 서브클래스에서 반드시 재정의 되어야 함
        System.out.println("첫번째 야옹이");
    }
}
 
class SecondCat extends Cat{
    void call(){
        System.out.println("두번째 야옹이");
    }
}
cs


실행 결과 화면



**

추상메서드를 재정의 하지 않을 경우 컴파일러는 에러를 발생시킵니다. 그러므로 추상메서드는 반드시 재정의 되어야합니다.


**

추상클래스는 해당 클래스를 통해 만들어낸 객체가 전혀 객체의 모습을 띄지 못할때, 해당클래스가 객체를 생성할 수 없도록 사용됩니다.


추상 : 무엇인가 덜 구체화된 것

객체 : 상태와 행동을 가진 것

클래스 : 객체를 만들기 위한 틀

초기화 : 클래스를 이용하여 객체 생성




인터페이스

 - 추상클래스와 비슷한 기능을 하지만 극단적인 경우이다.

 - 추상메서드와 상수로만 이루어져 있다.(=로직을 작성할 수 없음)

 - 다중 상속이 가능하다.

추가 설명



인터페이스 형식

1
2
3
4
5
interface 인터페이스명 [extends 상속받을 인터페이스명,,,,]{
    public abstract void 추상메서드명1();
    // public abstract 생략 가능
    void 추상메서드명2();
}
cs


클래스가 인터페이스를 참조하게 될 경우 형식

1
2
3
class 클래스명 extends 상속받을클래스명 implements 인터페이스명{
    내용
}
cs


인터페이스 구현 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
interface catWorld{
    public void call();
}
 
 
public class InterfaceTest implements catWorld{
    
    public void call() { //오버라이드
        System.out.println("야옹야옹!");
    }
    
    public static void main(String[] args) {
        InterfaceTest it = new InterfaceTest();
        
        it.call();
    }
 
}
 
cs


실행 결과 화면



**

클래스에 인터페이스 상속 시 인터페이스 내에 정의된 모든 추상메서드를 구현(오버라이드) 해야만 정상적인 컴파일이 가능합니다.




인터페이스와 추상클래스의 공통점

 - 추상클래스와 인터페이스는 선언만 있고 구현 내용이 없다.

 - 그래서 자기 자신이 new를 통해 객체를 생성할 수 없으며, 상속받은 자식만이 객체를 생성할 수 있다.

 - 상속받은 자식이 구현을 반드시 하도록 해야할 때 사용한다.

 - JAVA에서는 type이 지정되있기 때문에 선언된 type과 자식의 type이 같아야만 한다.


인터페이스와 추상클래스의 차이점

인터페이스(Interface)

추상클래스(Abstract Class) 

 구현 객체의 같은 동작을 보장하기 위함

추상클래스를 상속받아 기능을 이용하고, 확장시키기 위함 

 다중 상속 가능

다중 상속 불가능 

 추상메서드만 가능

일반메서드+추상메서드 가능

 상수+추상메서드 형태

일반변수(가능)+일반메서드(가능)+추상메서드 형태 

 생성자와 일반변수를 가질 수 없음

생성자와 일반변수 모두 가질 수 있음 

 implments

extends 

 메서드 선언만 가능

메서드의 부분적인 구현이 가능 



**

인터페이스를 상속받는 클래스는 반드시 인터페이스에 있는 메서드를 다 구현해야 하지만, 추상클래스를 상속받는 클래스는 추상메서드만 구현하고 일반메서드는 사용하지 않아도 문제가 없습니다.



**

다형성에 대한 개념을 이해하면 인터페이스를 더 정확히 알 수 있습니다.


interface : 동물

method : 먹는다, 걷는다, 잔다

implements(구현체) : 고양이, 원숭이, 닭


동물들은 모두 먹고, 걷고, 잠을 자지만 동물들마다 그 방식은 다릅니다. 

구현체에서는 동물들이 각각 먹고, 걷고, 자는 방식을 구현하는데 같은 "먹는다"라는 동사에서 동물마다 여러가지 형태로 구현할 수 있기때문에 다형성이라고 합니다.


고양이는 네발로 걷고, 원숭이는 두발 또는 네발, 닭은 두발로 걷습니다. 먹거나 자는 방법도 각각 다르죠.

그래서 동물이 먹는다, 걷는다, 잔다라는 틀만 만들어놓고 그 틀안에서 각각의 동물들에게 맞는 메서드를 구현하는 것입니다.


소스로 구현을 하자면

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
56
57
58
59
60
61
62
63
64
65
66
67
68
package helloJava;
 
 
    interface animals{
        public void eat(String bab);
        public void work(String move);
        public void sleep(String zzz);
    }
    
    class Cat implements animals{ //고양이
        public void eat(String bab) {
            System.out.println("고양이는 "+bab+"을 먹어요.");
        }
        public void sleep(String zzz) {
            System.out.println("고양이는 "+zzz+"자요.");
        }
        public void work(String move) {
            System.out.println("고양이는 "+move+"걸어요.");
        }
    }
 
    class Monkey implements animals{ //원숭이
        public void eat(String bab) {
            System.out.println("원숭이는 "+bab+"을 먹어요.");
        }
        public void sleep(String zzz) {
            System.out.println("원숭이는 "+zzz+"자요.");
        }
        public void work(String move) {
            System.out.println("원숭이는 "+move+"걸어요.");
        }
    }
 
    class Chicken implements animals{ //닭
        public void eat(String bab) {
            System.out.println("닭은 "+bab+"을 먹어요.");
        }
        public void sleep(String zzz) {
            System.out.println("닭은 "+zzz+"자요.");
        }
        public void work(String move) {
            System.out.println("닭은 "+move+"걸어요.");
        }
    }
 
 
public class InterfaceTest{
    
    public static void main(String[] args) {
        Cat cat = new Cat();
        Monkey mo = new Monkey();
        Chicken ch = new Chicken();
        
        cat.eat("생선");
        mo.eat("과일");
        ch.eat("사료");
        
        cat.work("네발로");
        mo.work("네발 또는 두발로");
        ch.work("두발로");
        
        cat.sleep("엎드려서");
        mo.sleep("누워서");
        ch.sleep("서서");
    }
 
}
 
cs

실행 결과 화면


인터페이스에서는 각 동물들이 무엇을 먹고, 어떻게 걷고, 자는지 구현하도록 되어있습니다.

그렇기때문에 각각의 동물(클래스)들이 animals라는 인터페이스를 상속받을 시 eat, work, move 메서드를 오버라이드 하여 구현하여야 합니다. 그리고 고양이의 자는 방법이 달라지더라도 원숭이나 닭에게는 아무런 영향이 없습니다. 



그렇다면 추상화 클래스는 언제 쓰는것이 좋을까요?



어미고양이(부모클래스) : 야생고양이

 - 자는 방법 (메서드)

 - 집에서 자는 방법 (추상화 메서드)

새끼고양이(자식클래스) : 집고양이

 - 자는 방법(메서드)

 - 집에서 자는 방법(메서드)

 




어미고양이는 야생고양이기 때문에 야생에서 자는 방법은 알지만 집에서 자본적이 없어서 집에서 자는 방법은 모릅니다.

새끼고양이는 사람의 도움을 받아 집에서 살게 되었을 때 집에서 자는 방법을 터득하기 때문에 추상화 메서드로 구현하였습니다.


어미고양이는 자는 방법을 아기고양이에게 알려줬습니다.(sleep(), 일반메서드)

아기고양이는 인간과 함께 집에 살면서 집에서 자는 방법을 새로 터득하였습니다.

어미고양이(부모클래스)에게 있는 내용을 오버라이드 했지만 아기고양이(자식클래스)는 집에서 자는 많은 방법을 구현하게 되었습니다.

(추상클래스는 부모클래스보다 더 많이 구현되는 경우가 대부분)



소스로 구현을 해보자면

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
package helloJava;
 
public class AbstractTest {
    public static void main(String[] args) {
        
        BabyCat bc = new BabyCat();
        bc.sleep();
        bc.homeSleep();
        
    }
}
 
abstract class Cat{ // 어미 고양이
    void sleep(){ //자는법
        System.out.println("야생에서는 눈에 띄지않는 안전한 곳에서 잡니다.");
    }
    abstract void homeSleep(); // 집에서 자는 방법(추상메서드) - 어미는 구체적으로 방법을 모름
    
}
 
 
class BabyCat extends Cat{ // 어미고양이의 영향을 받은 새끼고양이
    
    void homeSleep(){ // 집에서 자는 방법
        System.out.println("집사 위에서 잡니다.");
        System.out.println("침대 위에서 잡니다.");
        System.out.println("책상 위에서 잡니다.");
        System.out.println("노트북 위에서 잡니다.");
    }
}
 
cs



어미는 야생에서 자는 방법(sleep())을 알지만 집에서 자는 방법은 모릅니다. 하지만 새끼고양이는 어미고양이게 배운 야생에서 자는 방법과 집에서 배운 집에서 자는 방법 모두 알고있지요.


**

정리를 해보자면 인터페이스는 다형성에 초점을 맞추어 사용하고, 상속은 부모 - 자식의 관계로써 부모가 갖고있는 기능을 받을 수도 있고, 기능을 더 추가하거나 수정할 수도 있습니다.(?)









반응형

'프로그래밍 > Java' 카테고리의 다른 글

오버로딩과 오버라이딩 차이와 예제  (5) 2021.01.15
자바(JAVA) 상속/ 생성자/ SUPER 예약어  (1) 2016.10.06
자바 기초 문제  (4) 2016.09.29

댓글

💲 추천 글