갑자기 궁금해졌다. 다음과 같다.
print : 괄호안 내용을 단순히 출력. 개행문자(=줄바꿈문자=\n) 포함안됨.
printf : C에서의 printf와 동일. %d, %s 등을 쓰기위해 사용. 개행문자 포함X
println : 괄호안 내용을 출력한 후 마지막에 개행문자가 포함되어 있어 출력후 한 줄 띄워짐.
'생성자' 라는 것을 이용하면 메소드를 정의하지 않아도 인스턴스의 초기화를 진행할 수도 있다. 즉, 객체가 생성되는 시점부터 인스턴스(초기값)를 설정하기 위해 사용한다.
코드로 보면 다음과 같다.
package org.opentutorials.javatutorials.constructor;
class Calculator {
int left, right;
/* 생성자 (Contructor)
* 생성자를 생성할 때는 클래스 이름과 똑같아야 한다. 이름이 똑같다는 것이 중요하다.
*/
public Calculator(int left, int right) {
this.left = left;
this.right = right;
}
public void sum() {
System.out.println(this.left + this.right);
}
public void avg() {
System.out.println(this.left + this.right / 2);
}
}
public class contructor {
public static void main(String[] args) {
// 여기서 Calculator는 클래스가 아닌 생성자임을 나타낸다.
Calculator c1 = new Calculator(10, 20);
c1.sum();
c1.avg();
}
}
주석에도 달아놓았지만, 생성자를 만들때는 클래스의 이름과 동일해야 한다는 것이다.
객체지향에서 아주 중요한 개념이다. 이는 재활용성과도 이어지는데, 상속은 객체지향의 재활용성을 극대화시킨 프로그래밍 기법이라고 볼 수 있다.
상속이란 어떤 객체가 있을 때 그 객체의 필드(변수)와 메소드를 다른 객체가 물려 받을 수 있는 기능을 상속이라고 한다.
코드를 통해 살펴보자
class Calculator {
int left, right;
public void setOperands(int left, int right) {
this.left = left;
this.right = right;
}
public void sum() {
System.out.println(this.left + this.right);
}
public void avg() {
System.out.println(this.left + this.right / 2);
}
}
덧셈과 평균을 구하는 Calculator 클래스가 있다.
이 클래스에 빼기(Substract)기능을 추가하고 싶다. 물론, Substract 메소드를 직접 추가하여 사용할 수도 있지만. 상속을 이용하여 더 쉽게 구현할 수 있다.
우선, 아래와 같은 경우에 속한다면 객체에 메소드를 추가하는 것을 어려울 것이다.
상속을 이용하면 기존의 객체를 수정하지 않으면서 새로운 객체가 기존 객체를 기반으로 만들어진다. 이 때, 기존 객체를 부모 클래스, 새로 만들어진 객체를 자식 클래스라고 부른다.
실제 코드로 확인해보자.
package org.opentutorials.javatutorials.inheritance;
class Calculator {
int left, right;
public void setOperands(int left, int right) {
this.left = left;
this.right = right;
}
public void sum() {
System.out.println(this.left + this.right);
}
public void avg() {
System.out.println(this.left + this.right / 2);
}
}
class SubstractionableCalculator extends Calculator {
public void substract() {
System.out.println(this.left - this.right);
}
}
public class inheritance {
public static void main(String[] args) {
SubstractionableCalculator c1 = new SubstractionableCalculator();
c1.setOperands(10, 20);
c1.sum();
c1.avg();
c1.substract();
}
}
전체 코드이다. 아래 부분을 다시 살펴보자.
class SubstractionableCalculator extends Calculator {
public void substract() {
System.out.println(this.left - this.right);
}
}
extends를 이용하여 부모 클래스(super class)에서 선언, 정의된 것들을 그대로 가져오며, 자식 클래스(sub class)는 오버라이딩 할 필요 없이 부모의 메소드나 변수를 그대로 사용할 수 있다.
즉, 부모 클래스가 가진 것들 + 연장선이다.
부모의 sum
, avg
를 가져왔으며, 추가적으로 substraction
을 구현한 것이다.
클래스 다이어그램으로 표현하면 위와 같다.
갑자기 implements 와 차이점이 궁금해진다.
복습 개념으로, 이번엔 곱하기 기능이 있는 계산기를 만들어보자.
package org.opentutorials.javatutorials.inheritance;
class Calculator {
int left, right;
public void setOperands(int left, int right) {
this.left = left;
this.right = right;
}
public void sum() {
System.out.println(this.left + this.right);
}
public void avg() {
System.out.println(this.left + this.right / 2);
}
}
class SubstractionableCalculator extends Calculator {
public void substract() {
System.out.println(this.left - this.right);
}
}
class MultiplicationableCalculator extends Calculator {
public void multiplication() {
System.out.println(this.left * this.right);
}
}
public class inheritance {
public static void main(String[] args) {
// SubstractionableCalculator c1 = new SubstractionableCalculator();
// c1.setOperands(10, 20);
// c1.sum();
// c1.avg();
// c1.substract();
MultiplicationableCalculator c2 = new MultiplicationableCalculator();
c2.setOperands(10, 20);
c2.sum();
c2.avg();
c2.multiplication();
}
}
그렇다면, MC를 상속하고 있는 또 다른 클래스를 만들 수 있을까?
당연히 만들 수 있다.
코드를 보면 다음과 같다.
package org.opentutorials.javatutorials.inheritance;
class Calculator {
int left, right;
public void setOperands(int left, int right) {
this.left = left;
this.right = right;
}
public void sum() {
System.out.println(this.left + this.right);
}
public void avg() {
System.out.println(this.left + this.right / 2);
}
}
class MultiplicationableCalculator extends Calculator {
public void multiplication() {
System.out.println(this.left * this.right);
}
}
class DivisionableCalculator extends MultiplicationableCalculator {
public void division() {
System.out.println(this.left / this.right);
}
}
public class inheritance {
public static void main(String[] args) {
DivisionableCalculator c1 = new DivisionableCalculator();
c1.setOperands(10, 20);
c1.sum();
c1.avg();
c1.multiplication();
c1.division();
}
}
상속의 상속이 가능해진다.
이처럼 상속은 코드의 중복을 제거하거나, 부모가 가진 메소드를 자식이 활용가능하다는 점에서 재활용성도 좋아보인다.
그러나, 객체지향만의 강력한 특징처럼 보이긴 하나 굉장히 복잡해보인다.
생성자는 객체를 생성한다. 그 과정에서 해야 할 일들은 생성자 메소드에 지정해서 초기화 작업을 할 수 있다.
super는 부모 클래스를 의미한다. 즉, 부모 클래스로부터 상속받은 필드나 메소드를 자식 클래스에서 참조하는 데 사용하는 참조 변수이다.
인스턴스 변수의 이름과 지역 변수의 이름이 같을 경우 인스턴스 변수 앞에 this 키워드를 사용하여 구분할 수 있다.
이와 마찬가지로, 부모 클래스의 멤버와 자식 클래스의 멤버 이름이 같을 경우 super 키워드를 사용하여 구별할 수 있습니다.
이렇게 자바에서는 super 참조 변수를 사용하여 부모 클래스의 멤버에 접근할 수 있다.
this와 마찬가지로 super 참조 변수를 사용할 수 있는 대상도 인스턴스 메소드뿐이며, 클래스 메소드에서는 사용할 수 없다.
자식 클래스의 생성자에서 super 메서드(super()
)를 사용할 때 주의할 점은 super가 가장 먼저 나타나야 한다는 점이다. 부모가 초기화되기 전에 자식이 초기화되는 일을 방지하기 위한 정책이다.
super와 super()의 차이가 있다. 후에 다시 정리하자. 참고 자료