저를 포함한 초보자분들에게 도움이 됐으면 좋겠습니다.
초보자분들은 수박 겉핥기 식으로 알고 넘어가지 마시고, 조금이라도 왜 이렇게 프로그램이 돌아가는지 알고 가시는 시간이 됐으면 좋겠습니다.

오늘은 자바 프로그램에 있어서 유용하게 사용할 수 있는 키워드를 몇 가지 살펴보고자 합니다.
상속, 객체를 배우셨으면 당연히 알아야 하는 this 와 super를 알아보겠습니다.

첫 번째로 this - 이것을 뜻하는 영어인데요.
자바에서 '이것' this는 < 메소드를 부른 객체 > 정도로 생각하시면 됩니다.
메소드를 수행할 때, 우리는 객체를 생성하여 객체. 메소드로 메소드를 수행하게 되죠.
this는 메소드 안에서만 사용할 수 있습니다. 이유는 간단합니다. 위에서 말했듯 A.메소드 형태로 메소드를 부르면, A 객체 안에 있는 메소드를 수행하는 거죠. 이렇게 A.메소드 형태는 현재 어떤 객체를 이용하고 있는지 알 수 있는 징표가 됩니다. 이렇기 때문에 this는 A를 나타낼 수 있는 것이죠.
만약 메소드가 아닌 곳에서 선언하게 된다면, 객체명.~~~로 접근을 하는 것이 아니기에 this는 어떤 객체를 가리키는지 알 수가 없죠. 결국 this는 사용 못 하게 되는 것이죠. (변수는 객체명.변수 로 접근하지만 이것이 끝이기에 this를 사용하여 할 수 있는 것이 없습니다.)
이와 같은 이유로 static 메소드도 동일합니다. static메소드는 객체와 상관없이 하나를 공유하는 메소드라고 잠깐 설명드렸는데요.
static메소드는 객체를 생성하지 않아도 클래스명.static메소드명으로 호출이 가능합니다. 이와 같이 객체가 없어도 호출이 가능하기에 this의 사용을 허용하지 않습니다.

다음은 super입니다. 현재 객체를 나타내는 this가 있다면, super는 상위 클래스 객체를 나타내는 겁니다. super는 상속받은 자손 객체에서 사용할 수 있습니다. 예를 보시죠.


(1)public class parent {
	public void say() {
		System.out.println("부모");
	}
}
(2)public class son extends parent{
	public void say() {
		super.say();
		System.out.println("자손");
	}
	public static void main(String[] args) {
		son myson = new son(); // son 객체생성
		myson.say(); // 최종 출력 : 부모 자손
	}
}

parent를 상속받은 son 클래스가 있습니다. 저번 시간에 형 변환을 해서 parent에 있는 메소드를 수행하고자 했으나 실패를 했죠. 하지만 parent의 메소드를 수행하는 방법이 있다고 말씀드렸었습니다.
바로 super 키워드죠. (2) say() 메서드 안에 super.say()라고 되어있습니다. super 키워드는 자식-부모 관계(상속)에서 부모 객체라 생각하시면 되고, 부모객체.메소드를 사용하여 부모의 메소드를 수행할 수 있습니다. 조금 더 자세히 말하자면, 상속을 받은 son 클래스를 객체를 만들게 되면, son, parent 객체가 만들어져. myson이라는 객체에 들어 있다고 생각하시면 됩니다. 이 때문에 다형성, 형 변환이 가능한 것이기도 하고요. 어쨌든 myson은 son, parent 객체를 가지고 있기에 super라는 키워드를 사용하면, 현재 객체(son)의 부모(parent) 객체에 접근하여 부모의 메소드를 사용할 수 있는 것이죠.

마지막으로 final입니다.
final은 변수를 지정할 때 변하지 않는 '상수'로 많이 사용합니다.( 물론 다른 곳에서도 사용합니다.)
final 키워드를 가지게 되면, 바꿀 수 없습니다. final 변수명 = ~~~;로 선언하게 된다면, 선언한 곳에서만 내용을 바꿀 수 있습니다.


(3)public class Solution {
	
	public final int k = 3; //선언 한 곳 
	
	public static void main(String[] args) {
		Solution a = new Solution();
		a.k=6; // X 오류발생
	}
}

(3) 코드는 fianl로 int를 선언해보았습니다. 객체 a를 만들어 a.k로 접근하여 값을 변경하려니 오류가 발생합니다. 이처럼 final은 선언한 곳 에서만 값을 바꿀 수 있지 다른 곳에선 바꿀 수 없는 '상수'가 됩니다. 그럼 final 메소드를 알아보죠.


(4)public class parent {
	  public final void say() {
	  	System.out.println("부모");
	}
}
---------------------------------------------------------------------
public class son extends parent{

	public void say() {   // X 오류
		System.out.println("자손");
	}
	public static void main(String[] args) {
		son myson = new son(); 
		myson.say(); 
	}
}

(4) 코드에서 보듯이 상속 관계에서 parent의 say를 final로 지정하였습니다. 다시 말씀드리지만 final은 변할 수 없는 상태가 되는 것과 같습니다. 그래서, 자손 son에서 say를 오버라이딩을 시도하니 오류가 나오는 것을 알 수 있습니다.(오버라이딩은 메소드를 재정의하는 것이기 때문에)

다음은 final 클래스입니다.


(5)public final class parent { }
-----------------------------
   public class son extends parent{ }  //오류 

(5) 번 코드는 fianl로 선언된 parent를 son에 상속해주려고 했더니 오류가 발생합니다. 이유는 '상속을 위해 디자인된 클래스를 제외한 클래스를 상속하여 프로그램의 디자인을 깨고, 예상치 못한 일이 발생하는 것을 막아주기 위한 수단'이라는 설명이 있습니다. 개인적으로 맞다고는 공감하지만 말이 어렵죠.
저는 이렇게 생각합니다.'오버라이딩이 될 수도 있으니까.' final 클래스는 메소드를 선언하면 final을 붙이지 않아도 final메소드가 됩니다. 위에서 보셨듯 final메소드는 자손에서 오버라이딩 할 수 없습니다.
이러한 '위험요소' 가 있기에 처음부터 제한했다고 생각합니다.
구구절절 길어졌지만, final을 사용하면 원치 않은 상속을 피할 수 있습니다.
또 final로 선언된 메소드는 실행 속도가 빠르다고 합니다. 

오늘은 여기까지입니다! 자바 프로그램에서 없어도 되지만 있으면 훨씬 도움이 되는 3가지 키워드를 살펴보았습니다. 단순하게 이 3가지 키워드가 어떤 역할을 하는지 기억하셔야겠지만, 왜 사용 가능한지도 한번 곰곰이 생각해 보시면 더욱더 프로그래밍 하는데 도움이 되지 않을까 생각합니다.

다음 편은 추상 클래스 편을 써보겠습니다.

+ Recent posts