내일배움캠프 7일차 TIL - Java 객체지향개념(추상클래스, 인터페이스)

iy·2023년 12월 27일

TIL

목록 보기
6/37

추상 클래스(abstract class)

  • 미완성 설계도. 미완성 메서드를 갖고 있는 클래스
abstract class Player {
    abstract void play(int pos);
    abstract void stop();
    // 몸통 {}이 없는 미완성 메서드
}
  • 다른 클래스 작성에 도움을 주기 위한 것. 인스턴스 생성 불가
Player p = new Player(); //에러. 추상 클래스의 인스턴스 생성 불가
  • 상속을 통해 추상 메서드를 완성해야 인스턴스 생성 가능
class AudioPlayer extends Player {
    void play(int pos){ /* 내용 설계 */} //추상 메서드를 구현
    void stop() { /* 내용 생략 */ }
}

AudioPlayer ap = new AudioPlayer(); //ok 인스턴스 생성 가능(위에서 추상메서드를 구현해줬기 때문)

추상 메서드(abstract method)

  • 미완성 메서드, 구현부(몸통{})이 없는 메서드
/* 주석을 통해 어떤 기능을 수행할 목적으로 작성하였는지 설명한다. */
abstract 리턴타입 메서드이름();
  • 꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우
abstract class Player { //추상클래스
    abstract void play(int pos); //추상메서드
    abstract void stop(); // 추상메서드
}

class AudioPlayer extends Player {
    void play(int pos){ /* 내용 생략 */} //추상메서드를 구현
    void stop() { /* 내용 생략 */} //추상메서드를 구현
}

abstract class AbstractPlayer extends Player{
    void play(int pos){/* 내용 생략 */} //추상메서드를 구현
    // 두개 다 구현하면 완성된 메서드이지만 하나만 구현했기 때문에 미완성이므로 제어자 abstract붙여줘야 함
}

// 일부만 구현해도 되지만 그렇게 되면 여전히 미완성인 상태이므로 abstract 클래스인 것
  • 추상 메서드 호출 가능(호출할 때는 선언부만 필요)

추상 클래스의 작성

  • 여러 클래스에 공통적으로 사용될 수 있는 추상클래스를 바로 작성하거나 기존 클래스의 공통 부분을 뽑아서 추상클래스를 만든다.
class Marine {//보병
    int x, y;// 현재 위치
    void move(int x, int y){/* 지정된 위치로 이동 */}
    void stop(){/* 현재 위치에 정지 */}
    void stimPack(){/* 스팀팩을 사용한다. */}
}

class Tank { //탱크
    int x, y;// 현재 위치
    void move(int x, int y) { /* 지정한 위치로 이동 */}
    void stop() { /* 현재 위치에 정지 */}
    void changeMode(){/* 공격모드로 변경한다 */}
}

class DropShip { // 수송선
    int x,y; // 현재 위치
    void move(int x, int y){ /* 지정한 위치로 이동 */}
    void stop(){ /* 현재 위치에 정지 */}
    void load(){ /* 선택된 대상을 태운다. */}
    void unload(){/* 선택된 대상을 내린다 */}
}

이렇게 세개의 클래스에서 공통된 부분을 모아 추상 클래스를 만들어준다.
여기서 move()메서드는 지상과 공중이라는 차이 떄문에 구현부가 다를 것이다. 그래서 구현부는 불일치 하기 때문에 선언부만 abstract로 선언해서 뽑아낸다.

abstract class Unit {
    int x,y;
    abstract void move(int x, int y);
    void stop(){/* 현재 위치에 정지 */}
}

class Marine extends Unit {
    void move(int x, int y) { }
    void stimPack() {}
}

class Tank extends Unit {
    void move(int x, int y){}
    void changeMode(){}
}
class DropShip extends Unit {
    void move(int x, int y){}
    void load(){}
    void unload(){}
}

이렇게 함으로써 코드의 중복을 줄일 수 있다.

Unit[] group = new Unit[3];
group[0] = new Marine();
group[1] = new Tank();
group[2] = new DropShip();

for(int i = 0 ; i < group.length;i++){
    group[i].move(100,200);
}

다형성 특징 때문에 이렇게 각자의 객체를 배열에 담을 수 있다.
Unit 배열 group[i]에는 move메서드 호출이 가능하다.
이때 호출은 추상메서드를 호출하는 것이 아닌 구현된 메서드 move()가 호출되는 것이다.

Object[] group = new Object[3];
group[0] = new Marine();
group[1] = new Tank();
group[2] = new DropShip();

for(int i = 0 ; i < group.length;i++){
    group[i].move(100,200);
}

/* 에러!!!!! Object 클래스에 move메서드가 정의되어 있지 않다. */

추상클래스 작성의 장점
1. 코드 중복 제거
2. 추상클래스를 상속받는 자식클래스의 설계도 쉽게 작성(중복된 부분이 추상클래스로 묶여있으므로)
3. 코드 관리(수정)가 용이
4. 단계별로 추상클래스를 만들어놓으면 상속받으면서 점점 구체적으로 완성되가는 모습을 볼 수 있음


인터페이스(interface)

  • 추상메서드의 집합

  • 구현된 것이 전혀 없는 설계도. (껍데기, 모든 멤버가 public)

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

    • 추상 클래스 : 일반 클래스에 추상메서드가 있는 것
    • 인터페이스 : 구현된 것이 전혀 없는 곳에 추상메서드만 나열해놓은 것
interface 인터페이스이름 {
    public static final 타입 상수이름 =값;
    public abstract 메서드이름(매개변수목록);
}
/* public static final, public abstract 는 생략 가능 무조건 붙어야 하는 부분이기 때문에 생략해도 구현되어있다고 봄 */
  • 인터페이스의 조상은 인터페이스만 가능(Object가 최고 조상 아님)
  • 다중 상속이 가능(추상메서드는 충돌해도 문제 없음) : 구현부 없이 선언부만 있어서 구현된 부분의 충돌이 없기 때문

인터페이스의 구현

  • 인터페이스에 정의된 추상 메서드를 완성하는 것
class 클래스이름 implements 인터페이스이름{
    //인터페이스에 정의된 추상메서드를 모두 구현해야 한다.
}
class Fighter implements Fightable {
    public void move(int x, int y){}
    public void attack(Unit u) {}
}
//추상클래스의 구현을 완성시키는 것과 같고 상속을 implements로 받는다는 것이 다름
  • 일부만 구현하는 경우, 클래스 앞에 abstract 를 붙여야 함

인터페이스를 이용한 다형성

  • 인터페이스도 구현 클래스의 부모? 엄밀히 보면 아니지만 다름없다.
class Fighter extends Unit implements Fightable {
    public void move(int x, int y){}
    public void attack(Fightable f) {}
}// 다중 상속의 문제는 충돌의 문제인데 구현부가 없는 추상메서드 집합인 인터페이스는 여기서 문제가 없기 때문에 가능하다.
Unit u = new Fighter();
Fightable f = new Fighter();

f.move(100,200);
f.attack(new Fighter());

interface Fightable {
    void move(int x, int y);
    void attack(Fightable f);
}// 자손객체 호출하는 건 가능한 대신 존재하는 두개만 호출 가능하고 사용가능하다.
  • 인터페이스 타입 매개변수는 인터페이스 구현한 클래스의 객체만 가능
  • 인터페이스를 메서드의 리턴타입으로 지정할 수 있다.

인터페이스의 장점

  • 인터페이스
    • 두 대상(객체)간의 연결, 대화, 소통을 돕는 중간 역할을 한다.
  • 선언(설계)과 구현을 분리시킬 수 있게 한다.
    • 중간 역할을 하는 껍데기인 인터페이스가 존재하면 변경에 유리함
  • 인터페이스 덕분에 B가 변경되어도 A는 안 바꿀 수 있게 된다.(느슨한 결합)
/* 직접적인 관계의 두 클래스 (A-B : 강한 결합) */
class A {
    public void methodA(B b){
        b.methodB();
    }
}

class B {
    public void methodB() {
        System.out.println("methodB()");
    }
}

class InterfaceTest {
    public static void main(String args[]){
        A a = new A();
        a.methodA(new B());
    }
}
/* 사이에 인터페이스가 존재하는 두 클래스 (A-B : 느슨한 결합) */
class A {
    public void methodA(I i){
        i.methodB();
    }
}
// 사이에 인터페이스가 존재하면 인터페이스를 통해 methodB를 호출하기 때문에 B와 직접적인 관계가 없어짐

Interface I { void.methodB(); } //선언

class B implements I {
    public void methodB() { //구현
        System.out.println("methodB()");
    }
}
// B의 method()를 추상 메서드로 갖는 인터페이스 작성(선언과 구현을 분리)

class InterfaceTest {
    public static void main(String args[]){
        A a = new A();
        a.methodA(new B());
    }
}

인터페이스 장점 정리

  • 개발 시간을 단축할 수 있다.
  • 변경에 유리한 유연한 설계가 가능하다.
  • 표준화가 가능하다. (ex. JDBC)
  • 서로 관계없는 클래스들을 관계를 맺어줄 수 있다.

✔ 오늘 한 일
1. Java 객체지향개념 강의 듣기(추상화, 인터페이스)
2. SQL 5주차 강의 듣기
3. 프로그래머스 문제 풀기

👀
객체지향 개념 강의를 다 들었다. 본격적으로 Java 교육 들어가기 전에 객체지향 개념은 공부하고 싶었는데 계획대로 할 수 있어서 뿌듯하다. 강의를 듣고 이해한 부분도 있지만 아직 부족함이 많다고 느꼈다. 들었던 강의를 조금씩이라도 반복해서 들어야겠다.

📑 참고(남궁성 강사님-자바의 정석 강의)
  1. https://youtu.be/9VgkoVFZvyk?si=eQFJaQ_R5H_3ALj1
  2. https://youtu.be/SBdXXWIB3To?si=DNzU3e4Mxpunq4nF
  3. https://youtu.be/s0gRBHqa0yg?si=5Ajl11Y1Y6x5Qa97
  4. https://youtu.be/eS2EXUSRolk?si=KysoFRGgOMCqLD_C
  5. https://youtu.be/EnBLkMYt1XQ?si=SZB4aGMyXXKtQXeb
  6. https://youtu.be/Su4Oqk2SclY?si=b3-QkfbpphCDzCU8
  7. https://youtu.be/vW1PylkVGuM?si=_Zr4D3iGSUBpwyWl

0개의 댓글