본문 바로가기

Java-Study

Java Study : 5주차 정리 - 추상 클래스

추상 클래스

추상 클래스는 구체적이지 않은 클래스로 abstract class 라고 하며, 추상 클래스가 아닌 클래슨느 concrete class라고 한다.

추상 클래스는 항상 추상 메서드를 포함하는데, 추상 메서드는 구현 코드가 없다.

int add(int x, int y) {
    return x + y;
}

{ } 안의 내용을 함수의 구현부라고 하며 이 부분이 없는 함수를 추상 함수라 하고 자바에서는 추상 메서드라고 한다.

추상 메서드는 선언만 하며 abstract 예약어를 사용하고 { } 대신 ;를 쓴다.

즉, 추상 메서드는 abstract 예약어를 사용항 선언만 하는 메서드이다.

abstract int add(int x, int y);

 

추상 클래스 구현

package abstractex;

public abstract class Computer {	//추상 클래스

	public abstract void display();
	public abstract void typing();
	public void turnOn()
	{
		System.out.println("전원을 켭니다.");
	}
	public void turnOff()
	{
		System.out.println("전원을 끕니다.");
	}
}
package abstractex;

public class DeskTop extends Computer{
    //상속받은 클래스는 추상 메서드를 포함한다.
    //때문에 상속을 받은 클래스를 추상 클래스로 만들거나 추상 메서드를 모두 구현해야 한다.


    @Override
    public void display() {
        System.out.println("DeskTop Display()");
    }

    @Override
    public void typing() {
        System.out.println("DeskTop Typing()");
    }

}
package abstractex;

public abstract class  NoteBook extends Computer{
    //추상 메서드를 모두 구현하지 않았기 때문에 상속받은 클래스를
    //추상 클래스로 만들었다.

    @Override
    public void display() {
        System.out.println("NoteBook Display()");
    }

}
package abstractex;

public class MyNoteBook extends NoteBook{
    //추상 메서드를 모두 구현했기 때문에 추상 클래스로 만들 필요는 없다.

    @Override
    public void typing() {
        System.out.println("MyNoteBook Typing()");
    }

}

 

추상 클래스를 만드는 이유

추상 클래스는 인스턴스로 생성할 수 없다.

package abstractex;

public class ComputerTest {

    public static void main(String[] args) {
        Computer c1 = new Computer();   //인스턴스 생성 불가능
        Computer c2 = new DeskTop();
        Computer c3 = new NoteBook();   //인스턴스 생성 불가능
        Computer c4 = new MyNoteBook();
    }
}

 

추상클래스는 상속을 하기 위해서 만든 클래스이다. 따라서 추상 클래스에서 구현하는 메서드는 하위 클래스에서도 사용할, 즉 하위 클래스에서도 구현 내용을 공유할 메서드를 구현한다.

  • 구현된 메서드 : 하위 클래스에서 공통으로 사용할 구현 코드, 하위 클래스에서 재정의할 수도 있다.
  • 추상 메소드 : 하위 클래스가 어떤 클래스냐에 따라 구현 코드가 달라짐

 

템플릿 메서드

틀이 있는 메서드이다.

package template;

public abstract class Car {

    public abstract void drive();
    public abstract void stop();
    public void startCar()
    {
        System.out.println("시동을 켭니다");
    }

    public  void turnOff()
    {
        System.out.println("시동을 끕니다.");
    }

    final public void run() //템플릿 메서드
    //자동차가 달리는 방법을 순서대로 구현        
    {
        startCar();
        drive();
        stop();
        turnOff();
    }
}

자동차 종류에 따라 구현 내용이 달라지는 부분은 추상 메서드로 만들고, 공통으로 사용하는 메서드는 추상 클래스에 구현하여 상속

package template;

public class AICar extends Car{

    @Override
    public void drive() {   //
        System.out.println("자율 주행합니다");
        System.out.println("자동차가 스스로 방향을 전환합니다.");
    }

    @Override
    public void stop() {
        System.out.println("스스로 멈춥니다.");
    }
}
package template;

public class CarTest {

    public static void main(String[] args) {

        System.out.println("=== 자율주행 하는 자동차 ===");
        Car myCar = new AICar();
        myCar.run();

        System.out.println("=== 사람이 운전하는 자동차 ===");
        Car hisCar = new ManualCar();
        hisCar.run();
    }

}

 

템플릿 메서드의 역할

템플릿 메서드는 실행 순서, 즉 시나리오를 정의한 메서드이므로 바뀔 수 없다. 그래서 템플릿 메서드는 final 예약어를 사용하여 선언한다. 메서드 앞에 final을 사용하면 상속받은 하위 클래스가 메서드를 재정의할 수 없다.

 

final 예약어

자바 프로그램에서 final 예약어는 변수, 메서드, 클래스에 사용할 수 있다.

  • 변수 : fianl 변수는 상수를 의미한다.
  • 메서드 : final 메서드는 하위 클래스에서 재정의할 수 없다.
  • 클래스 : final 클래스는 상속할 수 없다.

final 변수

package finalex;

public class Constant {

    int num = 10;
    final int NUM = 100;    //상수 선언

    public static void main(String[] args) {

        Constant cons = new Constant();
        cons.num = 50;
        //cons.NUM = 200;   //상수에 값을 대입하여 오류 발생

        System.out.println(cons.num);
        System.out.println(cons.NUM);
    }
}

하나의 자바 파일에서만 사용하는 상수 값은 해당 팔이 안에서 정의해서 사용할 수 있다.

하지만 여러 파일에서 공유해야 하는 상수 값은 한 파일에 모아 public static final로 선언하여 사용한다.

package finalex;

public class Define {

    public static final int MIN = 1;
    public static final int MAX = 99999;

    public static final int ENG = 1001;
    public static final int MATH = 2001;

    public static final double PI = 3.14;
    public static final String GOOD_MORNING = "Good Morning!";
}
package finalex;

public class UsingDefine {

    public static void main(String[] args) {

        System.out.println(Define.GOOD_MORNING);
        //static 으로 선언되었으므로 인스턴스를 생성하지 않고 클래스 이름으로 참조 가능하다.
        System.out.println("최솟값은 " +  Define.MIN + "입니다.");
        System.out.println("최댓값은 " +  Define.MAX + "입니다.");
        System.out.println("수학 과목 코드 값은 " + Define.MATH + "입니다.");
        System.out.println("영어 과목 코드 값은 " + Define.ENG + "입니다.");

    }

}

 

상속할수 없는 final 클래스

클래스를 final로 선언하면 상속할 수 없다. 그렇기 때문에 보안과 관련이 있거나 기반 클래스가 변하면 안 되는 경우에는 클래스를 final로 선언하여 사용한다.