Java - 기본기

22. 추상 클래스, 인터페이스, static, final

TerianP 2022. 3. 5.
728x90

1. 추상 클래스  - abstract class

추상 클래스는 [접근제어자] abstract class [클래스명] 으로 선언한다.

추상 메서드는 [접근제어자] abstract [return여부] [클래스명] 으로 선언한다.

  • 추상 클래스는 오직 상속만을 위해 탄생한 클래스로 다른 여러 클래스들의 공통된 필드 변수, 메서드들을 모아놓기 위해서 만들어졌다.
    • 이렇게 만들어진 공통된 부분을 만들어놓은 추상 클래스를 하위 클래스들에서 상속 받은 후 변수와 메소드을 사용하게 된다.
  • 일반 클래스가 설계도라면, 추상 클래스는 일종의 조감도라고 할 수 있다.
  • 추상 클래스는 인스턴스, 즉 객체 생성이 불가능하다!!! 다중 상속도 불가능!
  • 추상 클래스의 메서드는 크게 구현 메서드와 미구현 메서드로 나눌 수 있다.
    • 구현 메서드 : 메서드의 method body 부분이 있는 메서드 , 쉽게 생각하면 { } 가 있는 메서드. 이때 { } 괄호안에는 아무런 내용이 없어도 상관 없다. 메서드 바디가 있는 구현 메서드는 메서드 명 앞에 abstract 를 붙이지 않는다.
    • 미구현 메서드 : 메서드의 method body 부분이 없는 메서드, 즉 { } 괄호가 없는 메서드. 이렇게 메서드 바디가 없는 경우 무조건!! 반드시!! 메서드명 앞에 abstract 를 붙여야 한다.
  • 추상 클래스를 상속받은 클래스는 추상 클래스가 갖는 추상 메소드를 반드시 구현해야 한다.

2) StarCraft 통한 예시

  • 해당 클래스는 추상 클래스이다.
  • status() 메서드는 메서드 바디가 있는 메서드로 abstract 를 붙이지 않는다.
  • attack() 메서드는 메서드 바디가 없는 메서드로 abstract 를 붙인다.
public abstract class StarCraft_abstract {
	String name;
	String weapon;
	int x, y; // 위치
	int hp, at_point, de_point; // hp, 공격력, 방어력
	int mv_spd, at_spd; // 이동속도, 공격속도
	
	
	// 정보 출력을 위한 메소드
    // 메서드 바디가 있는 경우, abstract 를 붙이지 않는다.
	public void status(StarCraft_abstract unit) {
		System.out.println(unit+" 의 현재 정보를 출력합니다");
		System.out.println("이름 : "+unit.name);
		System.out.println("hp : "+unit.hp);
		System.out.println("공격력 : "+unit.at_point);
		System.out.println("방어력 : "+unit.de_point);
		System.out.println("이동 속도 : "+unit.mv_spd);
		System.out.println("공격 속도 : "+unit.at_spd);
	}
	
	// 메서드 바디가 없는경우 abstract 를 붙이지 않으면 에러가 발생!
	public abstract void attack(StarCraft_abstract unit);
}

2. 인터페이스 Interface

인터페이스는 class 대신 interface 를 통해 선언하고, implements 를 통해 사용한다 => 사실 말이 사용한다라는 것이지 상속과 똑같은 느낌이다...

  • 인터페이스는 일종의 클래스 기능 모음집이다. 앞서 공부했던 상속이 '부모 클래스의 확장 + 재사용'이라고한다면, 인터페이스는 인터페이스 안에 있는 '메서드의 기능 구현' 에 초점이 맞춰져 있다.
  • 인터페이스도 추상메서드와 마찬가지로 누군가 implements 해서 기능을 구현해야하기 때문에 객체(인스턴스) 생성이 불가능하다.
  • 인터페이스의 모든 메서드는 추상 메서드이다. 즉, 모든 메서드에는 public abstract 가 붙어야한다.
    • 모든 메서드가 추상 메서드라는 점 때문에 abstract 는 생략 가능하다.
    • 인터페이스의 추상 메서드는 반드시!! 구현되어야 한다.
  • 인터페이스의 멤버 변수는 상수가 된다. 즉 모든 변수 앞에 public static final 이 붙는다.
    • 이 때문에 모든 변수는 초기화된 값으로 끝까지 간다.

 

2) StarCraft 통한 예시

  • 사실 status 나 attack 가 굳이 추상 클래스 starCraft 에 있을 필요는 없죠. 따라서 주요 기능들은 모두 interface 로 빼주겠습니다.
  • StarFunction : 스타크래프트 유닛 주요 기능 => 현재 상태, 공격하기, 이동하기
public interface StarFunction {
	
	public abstract void status(StarCraft unit);
	public abstract void attack(StarCraft unit);
	public abstract void move(int x, int y);
}

 

  • StarFunction 인터페이스를 상속받은 StarCraft 입니다.
    • 상위 클래스가 되는 StarCraft 에서는 변수 선언과 정말로 하위 클래스 모두가 사용할 status 와 move 를 구현하겠습니다.
public abstract class StarCraft implements StarFunction{
	String name;
	String weapon;
	int x, y; // 위치
	int hp, at_point, de_point; // hp, 공격력, 방어력
	int mv_spd, at_spd; // 이동속도, 공격속도
	
	
	// 정보 출력을 위한 메소드
	// StarFunction 인터페이스를 상속받아서 오버라이드	
	@Override
	public void status(StarCraft unit) {
		System.out.println(unit+" 의 현재 정보를 출력합니다");
		System.out.println("이름 : "+unit.name);
		System.out.println("hp : "+unit.hp);
		System.out.println("공격력 : "+unit.at_point);
		System.out.println("방어력 : "+unit.de_point);
		System.out.println("이동 속도 : "+unit.mv_spd);
		System.out.println("공격 속도 : "+unit.at_spd);
		System.out.println("현재 위치는 "+x+" , "+y);
	}
	
	@Override
	public void move(int x, int y) {
		// TODO Auto-generated method stub
		this.x +=x;
		this.y +=y;
		System.out.println(x+", "+y+" 로 이동합니다");
	}
}

 

  • 마지막으로 제가 좋아하는 저그의 갓갓 히드라를 만들겠습니다.
    • 히드라 클래스는 StarFunction 인터페이스를 사용하는 StarCraft 를 상속받습니다. 
    • 부모 클래스인 StarCraft 에서 이미 status, move 를 구현해두었기 때문에 따로 구현 할 필요가 없습니다. 다만 attack 는 각자 스킬에 따라서 달라지기 때문에 히드라 클래스에서 구현하겠습니다.
package practice2;

public class Hydralisk extends StarCraft{ // 스타크래프트 클래스를 상속	
	
	private boolean burrow; 
	// 히드라는 탱크와 비슷하게 잠복하는 능력을 갖습니다.
	// 한번 잠복하는 경우 더이상 공격할 수 없으며 무적상태가 됩니다.

	Hydralisk(){
		System.out.println("히드라리스크 등장!");
		this.name = "히드라리스크";
		this.weapon = "바늘 가시뼈";
		this.x = 55;
		this.y = 60;
		this.hp = 100;
		this.at_point = 10;
		this.de_point = 0;
		this.mv_spd = 3;
		this.at_spd = 30;
		this.burrow = false;
	}
	
	Hydralisk(String name){
		// 영웅 히드라를 만드는 생성자입니다.
		// 이름을 주면 해당 이름으로 기본 능력치에서 일정한 수치만큼 뻥튀기된 영웅 히드라가 만들어집니다
		
		this(); // 기본생성자로 변수값 초기화
		
		// 이후 초기화된 값 + 1 ~ 10 까지의 랜덤한 값 추가
		this.name = name;
		this.hp += (int)(Math.random()*10)+1;
		this.at_point +=(int)(Math.random()*10)+1;
		this.de_point +=(int)(Math.random()*10)+1;
		this.at_spd +=(int)(Math.random()*10)+1;
		this.mv_spd +=(int)(Math.random()*10)+1;
		System.out.println("영웅 히드라 "+name+ "가 등장했습니다");
	}
	
	// 히드라의 능력임으로 매개변수는 히드라 객체와 boolean 타입을 받겠습니다.
	void change_form(Hydralisk h, boolean burrow) { 
		if(burrow == true) {
			System.out.println("히드라가 땅속으로 잠복합니다");
			System.out.println("능력치 변경에 주의해주세요");
			
			this.burrow = true;
			this.hp = 999999999; // int형 최대값
			this.at_point = 0;
			this.de_point = 0;
			this.mv_spd = 0;
			this.at_spd = 0;
			
		}else {
			System.out.println("히드라가 잠복에서 벗어납니다");
			System.out.println("능력치 변경에 주의해주세요");
			
			this.burrow = false;
			this.hp = 80;
			this.at_point = 10;
			this.de_point = 0;
			this.mv_spd = 3;
			this.at_spd = 30;
		}
	}
	
	@Override
	public void attack(StarCraft unit){
		if(this.burrow == false) {
			System.out.println(unit + " 를 공격합니다");
			System.out.println("가시뼈 슉슉슉");
			unit.hp -= this.at_point;
		}else {
			System.out.println("버로우 상태에서는 공격할 수 없습니다");
		}
	}

}

3. static - 메모리 영역에 고정된 친구들

static 은 변수, 메소드, 클래스 앞에 붙는다.

해당 변수와 메소드를 부를때는 클래스명.변수명 혹은 클래스명.메서드명 을 사용한다.

  • static 은 고정적인 이라는 의미를 갖는다. 즉, 이렇게 static 이 붙은 변수, 메서드, 클래스는 JVM 구동 시 메모리에 고정이 된다. 정확히는 static area 라는 메모리 영역에 올라간다. => 사실 클래스보다는 변수, 메소드에 많이 붙는다.
  • static 키워드를 사용하는 모든 것들은 static area 라는 메모리 영역에 올라가게 된다. 이 때문에 해당 키워드가 붙은 변수, 메서드는 해당 클래스의 인스턴스를 생성하지 않아도 사용 가능하다.
    • static area 에 존재하는 static 이 붙은 변수와 메서드는 모든 클래스와 메서드가 공유하게 된다.
    • 해당 변수와 메소드를 부를때는 클래스명.변수명 혹은 클래스명.메서드명 을 사용한다.
    • 주로 해당 변수가 다른 곳에서도 사용되어 공통된 값을 유지해야하는 경우 static 을 사용한다.
  • 아래처럼 TestStatic 클래스의 인스턴스 생성없이 바로 happen 변수와 getter, setter 메서드를 불러올 수 있다.
public class TestStatic {
	public static String happen;
	
	
	public static String getHappen() {
		return happen;
	}

	public static void setHappen(String happen) {
		Hydralisk.happen = happen;
	}
    
    
    
	public static void main(String[] args) {
    	
        // 인스턴스 없이 바로 소환 가능!
    	System.out.println(Hydralisk.happen);

    
		// 인스턴스 없이 바로!! => 클래스명.메서드명
		Hydralisk.setHappen("I'm static");
		System.out.println(Hydralisk.getHappen());
		
		
		
	}
}

4. final - 나는 변하지 않는다

  • final 키워드는 말 그대로 마지막, 최후의 뭐 이런 의미를 갖는다.
  • 이에 따라서 final 키워드가 붙은 클래스와 변수, 메서드는 아래와 같은 특징을 갖는다.
    • class : 더 이상 상속은 없음 => Final B extends A 인 경우, A에서 상속받는데는 상관이 없으나 C extends B 가 되는 순간 에러가 발생한다. 즉 final 키워드가 붙은 클래스는 더 이상 상속을 할 수 없다.
    • method : 오버라이드가 금지된다. 즉 해당 메서드의 기능을 고쳐쓰는 재정의가 불가능하며, 무조건 그대로 써야한다.
    • 변수 : 상수가 된다. 쉽게 이야기하면 한번 정해진 변수의 값이 그대로 고정된다.
		a = 15; // final 로 정해진 변수는 상수로 취급되며 다른 값으로 변경 불가능!!

5. 내용 정리!! - 추상 메서드와 인터페이스

오늘 내용에서 가장 중요한 것은 역시 추상 메서드와 인터페이스 이다.

추상 메서드와 인터페이스는 비슷하면서 다르다!! 이 부분을 한번 더 정리하고 넘어가도록 하겠다.

추상 메서드 - abstract class : IS A
추상 메서드는 A is a B 라는 특징을 갖는다. 예를 들어서 '강아지는 동물이다', '핸드폰은 전자기기이다' 갖은 경우 우리는 각각 동물, 전자기기를 추상 클래스로 만들고, 각각 강아지, 핸드폰으로 구현하게 된다.
즉, 추상 메서드는 A is a B 라는 특징으로 구제적인 A 가 추상적인 B 에 포함된다 라는 느낌이라고 생각하면 된다.

인터페이스 - interface : HAS A
반면 인터페이스는 A has a B 라는 특징을 갖는다. 예를 들어서 '강아지는 달리는 능력이 있다', '핸드폰은 인터넷 기능이 있다' 라는 것이다. 즉 인터페이스는 A 가 B 라는 기능, 능력을 갖는다에 초점을 갖는다.
만약 추상 클래스의 is a 가 된다면 추상적 개념인 '달린다' 에 강아지가 포함되어야 하는데 실제로는 이렇지 않다. 물론 각각 '달린다', '인터넷' 이라는 추상적인 개념이 있지만, 실제로 달린다에 강아지가 포함되는 것이 아니고, 핸드폰이 인터넷에 포함되지 않는다. 달린다와 인터넷은 강아지와 핸드폰 기능(능력)의 일부분일 뿐이다.

 

 

 

 

- 참고자료

https://vaert.tistory.com/101

 

[Java] Static 키워드 바로 알고 사용하자

자바를 한번쯤 공부해본사람이라면 static키워드를 모르지는 않을 것입니다. 하지만, 바르게 알고 있는 사람들은 그리 많지 않습니다. 자바경력자를 면접볼 때 static키워드에 대해서 질문하곤 합

vaert.tistory.com

 

자바에서 final에 대한 이해

 

자바에서 final에 대한 이해

Gatsby로 블로그 마이그레이션을 하여 이 링크를 클릭하면 해당 포스팅으로 갑니다. 감사합니다. http://blog.advenoh.pe.kr 1. 개요 final 키워드를 떠올릴 때면 그냥 상수로만 생각할 때가 종종 있습니다

advenoh.tistory.com

 

[Java] 추상화, 상속, 추상클래스와 인터페이스 비교, 다형성

 

[Java] 추상화, 상속, 추상클래스와 인터페이스 비교, 다형성

본 포스팅은 jisikTank 스터디에 참여하며 정리한 문서입니다. jisikTank Skill 지식 Git Repository 객체지향과 추상화(상속, 추상클래스, 인터페이스, 다형성) 추상화(Abstraction) 객체 지향 프로그래밍 키워

sdesigner.tistory.com

https://myjamong.tistory.com/150

 

[JAVA] 추상클래스 VS 인터페이스 왜 사용할까? 차이점, 예제로 확인 :: 마이자몽

추상클래스 인터페이스 왜... 사용할까? 우리는 추상클래스와 인터페이스에 대해서 알고 있냐고 누가 물어본다면 알고 있다고 대답을 하고있습니다. 그런데 이론적인 내용 말고 정작 "왜 사용하

myjamong.tistory.com

 

https://limkydev.tistory.com/197

 

[JAVA] 자바 인터페이스란?(Interface)_이 글 하나로 박살내자

1. 인터페이스 개념과 역할 인터페이스....이 글하나로 박살내자. (회사에서 존댓말을 많이 쓰기때문에 여기서라도 반말로 글을 써보고 싶음 ㅎ) 인터페이스는 뭘까?? 결론부터 말하면, 극단적으

limkydev.tistory.com

 

댓글