2021-06-23강의록_상속(추상 클래스)

instanceof

참조변수에 들어있는 객체의 타입을 검사하고자 할 때 쓴다.

부모 타입이면 모두 자식 타입으로 강제 형변환 할 수 있는 것이 아니다.
타입을 알아야(자식타입이 뭔지 알아야) 가능.

Parent parent = new Parent();
Child child = (Child) parent;

->> ClassCastException 예외 발생.

먼저 자식 타입인지 확인 후 강제 형변환 실행해야한다.
boolean result = 좌항(객체) instance 우항(타입)

public void method(Parent parent){
	if(parent instanceof Child){	//parent 매개변수가 참조하는 객체가 Child인지 먼저 확인
    Child child = (Child) parent;

추상클래스

  • 인스턴스를 생성할 수 없는 클래스
  • 추상method (시그니처만이 정의된 비어있는 메소드) 를 하나라도 가지고 있으면 추상클래스. >>Abstract Class
  • 추상클래스를 상속하려면 무조건 추상method를 실체화해서 구현해야 함. 강제성.
  • 추상클래스를 상속받은 자식클레스 => 실체클래스. Concrete Class
  • new 연산자로 객체 생성할 수 없다.
  • abstract 의 접근제한자는 public. (생략해도 컴파일러가 자동으로 public을 넣어준다)

익명자식객체

  • 익명 = 이름을 알 수 없다. (이름이 '없다' 가 아님!!)
    -> 이름이 분명히 있기는 한데, 그 이름을 알 수 없다는 뜻.

  • 자바 소스파일로 자식타입의 클래스를 만들지 않고 바로 자식객체를 만들어내는 것.
    주로 안드로이드 앱을 만들거나, 스프링 등 웹에서도 많이 사용한다.
    UI의 각종 버튼 클릭시 무언가 기능을 수행하는 코드를 만들어 낼 때 사용.

  • 자식 클래스가 재사용되지 않고,
    오로지 해당 필드와 변수의 초기값으로만 사용할 경우(자식객체 구현 문장이 간단할 때)
    빠르게 자식객체를 생성할 수 있고
    부모타입의 생성자를 무조건 호출할 수 있도록 new허용.
    (실행문장이 길어지면 별도의 소스파일을 생성하는것이 맞다)
    부모타입이 abstract이든 아니든 상관 없다!

  • new 클래스명 (생성자 매개변수) {}; << { }; 가 익명 자식객체 만들어주는 문법.
    중괄호 { } 내부에 클래스 블록과 같이 작성하면
    자바 컴파일러가 대신 클래스를 만들어 메소드영역에 clazz객체로 넣어준다.
    (클래스가 없이는 객체를 찍어낼 수 없으니까)

  • 익명 자식객체 코딩기법의 전제는 상속

Lvalue (부모타입의 참조변수)
Rvalue = new 부모타입명(생성자 매개변수에 전달할 인자들) {

	//여기가 클래스 블록.
	//상속받은 메소드를 재정의하거나
	//새로운 메소드를 선언해도 됨
};

import lombok.extern.log4j.Log4j;

@Log4j
public class TTT {

	public static void main(String[] args) {

		// 다형성-1 : 부모타입에 자식객체를 생성해서 대입
		Phone phone = new Phone("Yoseph") {

			public int age = 23;

			// 생성자를 가지지 못한다.
			// 익명클래스는 자바 컴파일러가 자동으로 만들기 때문에,
			// 생성자의 규칙상, 클래스의 이름과 동일하게 선언해야 하나,
			// 말 그대로 익명클래스이기 때문에, 자체 생성자 선언은 불가능하다.

			@Override
			public void turnOn() {
				log.debug("turnOn() invoked.");
				log.info("\t + owner : " + owner);
			} // turnOn

			@Override
			public void turnOff() {
				log.debug("turnOff() invoked");

				log.info("\t + owner : " + owner);
			} // turnOff

			@Override
			public void phoneMethod() {
				log.debug("phoneMethod() invoked");

				anonymousMethod();
			} // phoneMethod

			public void anonymousMethod() {
				log.debug("anonymousMethod() invoked");

				log.debug("\t + age : " + age);
			} // anonymousMethod

		}; // 익명자식객체구현 코딩기법

		Class clazz = phone.getClass();
		log.info("- clazz : " + clazz.getName());

		phone.turnOn(); 		// ok : 상속받은 메소드는 외부에서도 사용 가능
		phone.turnOff(); 		// ok
		phone.phoneMethod(); 	// ok

//      phone.age;                  //xx : 익명자식객체에 선언한 필드는 지역적으로만 사용됨.
//      phone.anonymousMethod();    //xx : 익명자식객체에 선언한 메소드는 지역적으로만 사용됨
	} // main

}// end class


->> 로그를 보면 phone 익명 자식객체의 클래스가 생성되었음을 확인할 수 있다.


Closure 클로저

클로저 : 생명주기가 다른 두 변수가 상호(일방) 참조할 때,
생명주기가 짧은 변수가 파괴되고 나서, 생명주기가 긴 참조변수에서
이 파괴된 변수의 값을 참조(=사용) 함으로서 발생하는 문제
=> 생명주기가 짧은 변수를 final 상수로 만들어서 JVM 메소드 영역(clazz객체의 상수풀Constatnt Pool)에 저장 >> 메소드영역은 프로그램 종료시까지 계속 살아있으므로, 생명주기가 가장 긴 형태로 만든다.


익명객체(extends하는 자식객체, implements하는 구현객체)에서 클로저 현상 발생.
이미 유효범위가 끝난 변수의 값을, 변수가 파괴되었는데도 생명주기가 다른 참조타입의 객체가
이미 파괴된 지역변수의 값을 계속 참조 가능하게 만드는 것.
참조타입 객체에서 지역변수를 참조하는 코드가 들어있는데, 지역변수는 이미 파괴되어 없음.
이런 상황을 클로저라고 한다.
java7 에서는 참조했던 생명주기가 다른(더 짧은) 변수의 값을 하드코딩 했었는데
java8 이후로는 자바 컴파일러가 자동으로 final 상수화 함.

좋은 웹페이지 즐겨찾기