[Java]객체지향프로그래밍2

황세호·2021년 5월 16일
0

Java

목록 보기
2/6

super


super는 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조 변수이다.

class SuperTest {
	public static void main(String args[]) {
		Chilc c = new Child();
		c.method();
	}
}

class Parent {
	int x = 10;
}

class Child extends Parent {
	int x = 20;
	
	void method() {
		System.out.println("x = " + x);
		System.out.println("this.x = " + this.x);
		System.out.println("super.x = " + super.x);
	}
}
// 실행 결과
// x = 20
// this.x = 20
// super.x = 10

super() - 조상 클래스의 생성자


  • this()와 마찬가지로 super() 역시 생성자이다. (super()는 조상 클래스의 생성자를 호출하는데 사용)
  • 자손 클래스의 인스턴스를 생성하면, 자손의 멤버와 조상의 멤버가 모두 합쳐진 하나의 인스턴스가 생성된다. -> 자손 클래스의 인스턴스가 조상 클래스의 멤버들을 사용할 수 있게 됨.
  • 이와 같은 조상 클래스 생성자의 호출은 클래스의 상속관계를 거슬러 올라가면서 계속 반복되며, 마지막으로 모든 클래스의 최고 조상인 Object 클래스의 생성자인 Object()까지 가서야 끝이 난다.

Object 클래스를 제외한 모든 클래스의 생성자 첫 줄에 생성자, this() 또는 super()를 호출해야 한다. 그렇지 않으면 컴파일러가 자동적으로 ‘super();’를 생성자의 첫 줄에 삽입한다.

제어자(modifier)


static - 클래스의, 공통적인

  • 클래스변수(static 멤버변수)는 인스턴스에 관계없이 같은 값을 갖는다. (하나의 변수를 모든 인스턴스가 공유)
  • static메서드는 인스턴스를 생성하지 않고도 호출이 가능해서 더 편리하고 속도도 더 빠르다.

final - 마지막의, 변경될 수 없는

  • 변수에 사용되면 값을 변경할 수 없는 상수가 되며, 메서드에 사용되면 오버라이딩을 할 수 없게 되고 클래스에 사용하면 자신을 확장하는 자손클래스를 정의하지 못하게 된다.
  • 인스턴스의 변수의 경우, final이 붙어도 생성자에서 초기화가 가능하다.

제어자의 조합

  1. 메서드에 static과 abstract를 함께 사용할 수 없다.

    • static메서드는 몸통이 있는 메서드에만 사용할 수 있기 때문이다.
  2. 클래스에 abstract와 final을 동시에 사용할 수 없다.

    • final은 클래스를 확장할 수 없다는 의미이고, abstract는 상속을 통해서 완성되기에 서로 모순되기 때문이다.
  3. abstract메서드의 접근 제어자가 private일 수 없다.

    • abstract메서드는 자손 클래스에서 구현해야 하는데, private이면 상속이 불가능하기 때문이다.
  4. 메서드에 private과 final을 같이 사용할 필요는 없다.

    • 접근 제어자가 Private인 메서드는 이미 오버라이딩이 될 수 없기 때문이다.

다형성


객체지향개념에서 다형성이란 ‘여러 가지 형태를 가질 수 있는 능력’을 의미하며, 자바에서는 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 함으로써 다형성을 프로그램적으로 구현하였다.
즉, 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 하였다는 것이다.

CaptionTv 클래스가 Tv 클래스를 상속받고 있다고 가정해보자. 그러면 우리는 아래와 같이 참조하도록 할 수 있다.

CaptionTv c = new CaptionTv();
Tv        t = new CaptionTv();

반대로

CaptionTv c = new Tv();

와 같은 참조는 불가능하다. 그 이유는 실제 인스턴스인 Tv의 멤버 개수보다 참조변수 c가 사용할 수 있는 멤버 개수가 더 많기 떄문이다.

그렇다면, 인스턴스의 타입과 일치하는 참조변수를 사용하면 인스턴스의 멤버들을 모두 사용할 수 있을텐데 왜 조상타입의 참조변수를 사용해서 인스턴스의 일부 멤버만을 사용하도록 할까??
이에 대한 답은 추후에 알아보도록 하겠다.

instance 연산자


void doWork(Car c) {
	if (c instanceof FireEngine) {
		FireEngin fe = (FireEngine)c;
		fe.water();
	} else if (c instanceof Ambulance) {
		Ambulance a = (Ambulance)c;
		a.siren();
		...
	}

	...

}

위의 코드는, Car타입의 참조변수 c를 매개변수로 하는 메서드이다. 이 메서드가 호출될 때, 매개변수로 Car 클래스 또는 그 자손 클래스의 인스턴스를 넘겨받겠지만 메서드 내에서는 정확히 어떤 인스턴스인지 알 길이 없다.
그래서 instanceof 연산자를 이용해서 참조 변수 c가 가리키고 있는 인스턴스의 타입을 체크하고, 적절히 형변환한 다음에 작업을 해야 한다.

profile
Developer

0개의 댓글