티스토리 뷰

 상속 (Inheritance)

: 자식 클래스가 부모 클래스의 멤버를 물려받는 것

자식이 부모를 선택해 물려받음 

 

※ 상속의 효과

1. 부모 클래스 재사용해 자식 클래스 빨리 개발 가능

2. 반복된 코드 중복 줄임

3. 유지 보수 편리성 제공

4. 객체 다형성 구현 가능 

 

 상속 대상 제한 

1.  부모 클래스의 private 접근 갖는 필드와 메소드 제외 

2.  부모 클래스가 다른 패키지에 있을 경우, default 접근 갖는 필드와 메소드도 제외 

 

※ 자식 객체를 생성하면 부모 객체도 생성되는가?

- 자식 객체 생성할 때는 부모 객체부터 생성 후 자식 객체 생성. 

- 컴파일러가 자동으로 자식 생성자에 super() 코드를 추가시켜준다.

주의) super는 반드시 자식 생성자에서 첫 째 줄에 써야 한다. 

 


 메소드 재정의 (Override)

- 부모 클래스의 상속 메소드를 수정해서 자식 클래스에서 재정의하는 것을 말한다. 

- 재정의할 때 접근 제한을 더 강하게 오버라이딩 불가하다. 더 넓게는 가능 

- 주의 : 부모의 메소드와 선언부가 같아야 한다. 

- 새로운 예외 throws 불가하다.

 

 메소드 재정의의 효과 

: 부모 메소드를 숨기는 효과를 가진다. 

 

※ super() : 부모 생성자 호출 

※ super : 부모 객체 참조 (this는 자신 객체 참조)


※ 어노테이션 

@Override  : 해당하는 메소드가 부모쪽에 있는지 확인해주는 어노테이션이다. (재정의할 때 쓰임)


※ final 

1. final 필드 : 수정 불가 필드

2. final 클래스 : 부모로 사용 불가한 클래스

[예 - String 클래스]

출처 : https://docs.oracle.com/javase/8/docs/api/

- class 앞에 final이 붙으면 자식 클래스를 만들지 못한다.

 

3. final 메소드 

     : 오버라이딩 할 수 없는 final 메소드이다. 즉, 부모를 final로 하면 자식이 재정의할 수 없다. 


※ protected 접근 제한자와 다형성 (매우 중요 ) 

public class Parent {
	//Field
	protected int field1; 
	// 같은 패키지에서는 쓸 수 있다 (디폴트와 같음), 일반 다른 패키지는 사용 불가능 
	// but 다른 패키지에 있지만 내 자식 클래스라면 protected로 지정된 필드나 메소드를 모두 사용할 수 있다. 
	
	//Constructor
	
	//Method
	protected void parentMethod() {
		System.out.println("parentMethod() 실행");
	}
}

 

※ 다형성 (Polymorphism)

: 다형성을 만드는 방법은 두 가지이다. 인터페이스와 상속.

사용 방법은 똑같은데 어떤 부품을 사용하느냐에 따라 성능이 달라진다. (실행 결과가 달라진다.)

 

▶ 다형성이 되려면 2가지 전제조건이 필요하다. 

  • 재정의
  • 자동 타입 변환(Promotion)

=> 상속은 재정의와 타입변환 이 두 가지를 만족하기 때문에 다형성을 만드는 기술에 이용되는 것이다. 

 

 

▶ 다형성의 효과

: 객체 부품화 가능. 예를 들어, 자동차의 drive() 메소드는 변하지 않지만

바퀴를 교체함으로써 같은 drive()를 호출했을 때  성능이 달라질 수 있다. 

 

▶ 자동 타입 변환(Promotion)

 : 프로그램 실행 도중에 자동적으로 타입 변환이 일어나는 것을 말한다. 

- 자식클래스타입이 부모클래스 타입으로 자동 타입 변환될 수 있다. 

public class Example {

	public static void main(String[] args) {

		Parent parent = new Child(); // 자동 타입 변환 
		parent.field1 = 5;
		parent.method1();
		parent.method2();
		
		Child child = (Child)parent; // 강제 타입 변환 
		child.field1 = 10;
		child.field2 = 10;
		child.method1();
		child.method2();
		child.method3();
		
	}

}

parent.method2() 가 부모가 아니라 자식의 오버로딩된 메소드가 호출되는 것이 매우 중요하다.

Parent 타입이라서 method1() 과 method2() 만 사용가능하고, 그 중에서 자식이 오버라이딩했다면 해당 메소드가 실행된다. 


※ 강제 타입 변환 (Casting)

▶ 조건

    : 자식 타입이 부모 타입으로 자동 변환된 이후, 다시 자식 타입으로 변환할 때만 유효하다. 

Parent p = new Child();
/*
   부모타입을 자식타입으로 강제 타입 변환하려면 조건이 필요하다. 
   자식이 부모타입으로 변환된 이후에 다시 자식으로 돌아오는 것만 가능하다 
*/
Child c = (Child)p;

 

▶ 강제 타입 변환이 필요한 경우 

  • 자식 타입이 부모 타입으로 자동 변환되면, 부모 타입에 선언된 필드와 메소드만 사용 가능하다.
  • 자식 타입에 선언된 필드와 메소드를 다시 사용해야 한다면 강제 타입 변환이 필요하다. 

※ 객체 타입 확인 (instanceof 연산자 )

▶ instanceof - 강제 타입 변환 전에 안전하게 객체 타입을 확인하는 연산자이다. 

public void method(Parent parent) {
	if(parent instanceof Child) { // parent 매개변수가 참조하는 객체가 Child 인지 조사 
		Child child = (Child)parent;  // 부모가 자식으로 강제 타입 변환 되려면 매개변수로 Child객체가 들어와야 한다. 
	}
	
}

  추상 클래스

- 완전한 설계도가 아니기 때문에 객체를 만들 수 없다. 

- 단지 공통된 부분만 빼서 만들다 보니까 그 자체만으로 무언가 만들기가 애매모호하다. 

- 추상 클래스는 new로 객체 생성을 할 수 없고, 반드시 상속을 통해서 부모 클래스로만 역할을 해야 한다. (단독 객체 X)

 

[추상 클래스의 용도]

1.  실체 클래스의 공통된 필드와 메소드의 이름을 통일할 목적 

2. 실체 클래스를 작성할 때 시간을 절약 

3. 추상클래스를 상속받아서 자식을 만들면 만드는 사람이 다 달라도 규격이 비슷해진다. 

package pr07.exam11;
/*
 * 클래스마다 공통된 부분을 가져와서 만든 클래스라면
 * abstract을 붙일 수 있다. 
 */
public abstract class Animal { 
	// 이 클래스를 객체로 쓰려는 것은 아니고, 단지 여러 클래스의 공통 부분을 빼서 만든 것이다. 
	
	public String name;
	public String kind;
	
	public void sleep() {
		System.out.println("잠을 잡니다.");
	}
	
	public void eat() {
		System.out.println("먹습니다. ");
	}

	public abstract void sound(); 
	/*  일반 클래스는 추상 메소드를 가질 수 없다.
	 *  추상 클래스만 추상 메소드를 가질 수 있다. 
	 *  
	 *  추상메소드는 자식쪽에서 재정의해서 써야 한다. 
	 */
}

※ 인터페이스 

: 인터페이스는 설계도가 아니다. 객체를 사용하기 위한 설명서이다.

(비교) 반면에 클래스는 설계도이다.  우리는 설명서를 보고 설계도를 만들 수 있다. 

 

[효과]

1.  개발 코드는 객체의 내부 구조를 알 필요가 없고 인터페이스의 메소드만 알고 있으면 된다. 

2. 개발 코드가 객체에 종속되지 않게 하여 객체가 교체할 수 있도록 하는 역할을 한다.

3. 개발 코드 변경 없이 리턴값 또는 실행 내용이 다양해 질 수 있다. 

4. 다형성도 가능. 개발 코드는 같아도 어떤 객체를 사용하냐에 따라 결과가 달라지기 때문이다.

 

▶ 인터페이스의 구성 멤버 (중요)

  • 상수 : 상수는 static final과 같은 특성을 가진다. 대문자, 초기값 준다. 
  • 추상 메소드 : 실행부가 없다. 단지 객체 사용 설명이다.
  • 디폴트 메소드 (자바 8 부터 추가됨)
  • 정적 메소드 (자바 8 부터 추가됨)

cf> 자바8부터 함수형 개발 기술이 포함되었다. 람다식을 보강하면서 디폴트 메소드와 정적 메소드가 추가되었다. 

      아직까지 현업에서는 디폴트 메소드와 정적 메소드를 많이 사용하지 않는다.

 

▶ 상수 필드 선언 

[public static final]  타입 상수명(대문자) = 값;

앞에 public static final은 관례적으로 생략한다. (자동적으로 컴파일 과정에서 붙음)

주의) 인터페이스의 모든 메소드는 public 접근 제한을 갖기 때문에 public 보다 더 낮은 접근 제한으로 작성할 수 없다. 

 

▶ 추상 메소드 선언 

- 인터페이스를 통해 호출된 메소드는 최종적으로 객체에서 실행된다.

- 인터페이스의 메소드는 실행 블록이 없는 추상 메소드로 선언한다. 

인터페이스 뒤에 있는 객체를 인터페이스를 구현한 객체라고 한다. 

앞에 public abstract를 생략하더라도 자동적으로 컴파일 과정에서 붙게 됨 

package pr08.exam01;

public interface RemoteControl { 
	// 상수 
	String COMPANY = "삼성"; // 이 앞에는 public static final이 생략되어 있다. 
	int MAX_VOLUME = 10; // 반드시 값을 지정해줘야 한다.  값을 변경할 수 없다. 
	int MIN_VOLUME = 1; 
	
	// 메소드 (객체 사용 설명) : 추상메소드이지만 추상메소드라고 잘 말하지 않는다. 
	void turnOn();   
	void turnOff();  
	void setVolume(int volume);
	
	/*
	 * 인터페이스는 사용 설명서이다. 
	 * 인터페이스를 구현한 클래스를 만들고 그 클래스로 객체를 생성한다. 
	 * 그 클래스에 실행 내용이 있겠금 모든 메소드를 재정의해주어야 한다. 
	 * 
	 * 
	 * 상수는 구현 객체에서 값을 제한하거나 참조하고 싶을 때 사용한다. 
	 */
}

 

- 자바는 다중상속을 허용하지 않는다. 

- 다중 인터페이스 의미 : 인터페이스A로도 사용가능하게 하고, 인터페이스 B로도 사용가능하게 한다. 


[인터페이스 다형성 예시]

https://docs.oracle.com/javase/8/docs/api/

//new ArrayList() 를 매개변수 list에 대입할 수 있겠구나!
void method(List list){

}

자바 도큐먼트

 

[실습]

package pr08.exam04;

public class Car {
	// Field
	public Tire t1; // 이 자리에 대입될 수 있는 것은 Tire 인터페이스로 사용가능한 것들이다.
	public Tire t2; // class XXX implements Tire , XXX 객체가 올 수 있다. 
	public Tire t3;
	public Tire t4;
	
	// Constructor
	
	// Method 
	public void run() {  //  다형성,, 어떤 객체가 들어가던 그 객체의 성질로 실행이 된다. 
		t1.roll();
		t2.roll();
		t3.roll();
		t4.roll();
	}

}
// 인터페이스는 상속과 결부시키지 말고, 단지 클래스가 인터페이스를 사용가능 하냐 아니야로 생각해야 한다.