자바의 정석 ch07. 객체지향 프로그래밍(2)-1

yuju9·2022년 2월 5일
0

1. 상속

상속의 정의

  • 상속: 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것
    ex. 새로 작성하려는 클래스 이름이 child이고 상속받고자 하는 기존 클래스의 이름이 Parent
class Child extends Parent {
	//...
}

클래스간의 관계

  • 상속관계: ~은 ~이다
  • 포함관계: ~은 ~을 가지고 있다.

단일 상속

  • 다중상속 허용X, only 단일 상속만 가능
  • 클래스 간의 관계가 보다 명확해지고 코드를 더욱 신뢰할 수 있게 만들어줌
class TVCR extends TV, VCR { //에러!!
	//...
}

Object 클래스 - 모든 클래스의 조상

  • Object 클래스: 모든 클래스 상속계층도의 최상위에 있는 조상클래스
  • 다른 클래스로부터 상속 받지 않는 모든 클래스들은 자동적으로 Object 클래스로부터 상속받게 함
class Tv /*자동적으로 'extends Object'가 추가됨*/ {
 	//...
}



2. 오버라이딩

  • 오버라이딩: 조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것
  • 비유
    종합병원이 진료한 환자 수를 제공하는 경우를 생각해 보자. 환자는 진료과목마다 다르다. 예를 들어, 소아과에서는 53명의 환자가, 외과에서는 61명의 환자가 진료했다. 이를 통해 종합병원이라는 부모 클래스의 메서드인 getNumberOfPatients()를 상속받은 진료과에서는 각각 다른 환자값을 출력할 수 있다.
class Hospital{

	int getNumberOfPatients()
	{
		return 500;
	}
    
}

class Pediatrics extends Hospital{

	@Override
	int getNumberOfPatients()
	{
		return 53 ;
	}
}

class SurgeryDepartment extends Hospital{

    @Override
    int getNumberOfPatients() 
    {
        return 61;
    }
    
}

오버라이딩의 조건

  1. 자손 클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와 이름이 같아야 한다.
  2. 자손 클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와 매개변수가 같아야 한다.
  3. 자손 클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와 반환타입이 같아야 한다.

→ 즉, 선언부가 서로 일치해야 한다.

  • 접근 제어자와 예외는 제한된 조건하에서만 다르게 변경할 수 있다.
  1. 접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
  2. 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없다.
  3. 인스턴스메서드를 static메서드로 또는 그 반대로 변경할 수 없다.

오버로딩 vs. 오버라이딩

  • 오버로딩: 기존에 없는 새로운 메서드를 추가
  • 오버라이딩: 조상으로부터 상속받은 메서드의 내용을 변경
class Parent {
	void parentMethod() {}
}

class Child extends Parent {
	void parentMethod() {} //오버라이딩
    void parentMethod(int i) {} //오버로딩
    
    void childMethod() {}
    void childMethod(int i) {} //오버로딩
}

super

  • super: 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수
  • super 대신 this를 사용할 수 있다. 그래도 조상 클래스의 멤버와 자손클래스의 멤버가 중복 정의되어 서로 구별해야하는 경우에만 super를 사용하는 것이 좋다.
class SuperTest2 {
	public static void main(String args[]) {
    	Child c = new Child();
        c.method();
    }
}

class Parent {
	int x = 10;
}

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

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

  • this() : 같은 클래스의 다른 생성자를 호출하는 데 사용
  • super() : 조상 클래스의 생성자를 호출하는데 사용
  • Object클래스를 제외한 모든 클래스의 생성자 첫 줄에는 생성자.this() 또는 super().를 호출해야한다. 그렇지 않으면 컴파일러가 자동적으로 'super();'를 생성자의 첫 줄에 삽입한다.


3. package와 import

패키지

  • 패키지: 클래스의 묶음
package 패키지명
/*주석과 공백을 제외한 첫 번째 문장이어야함*/
  • 클래스가 물리적으로 하나의 클래스파일(.class)인 것과 같이 패키지는 물리적으로 하나의 디렉토리이다.

import문

  • 컴파일러에게 소스파일에 사용된 클래스의 패키지에 대한 정보를 제공
import 패키지명.클래스명;
import 패키지명.*;



4. 제어자

  • 제어자: 클래스, 변수 또는 메서드의 선언부에 함께 사용되어 부가적인 의미를 부여. 클래스나 멤버변수와 메서드에 주로 사용됨
  • 접근 제어자 - public, protected, default, private
    ※ 한 번에 4가지 중 하나만 사용 가능
  • 그 외 - static, final, abstract, native, transient, synchronized, volatile, strictfp

static - 클래스의, 공통적인

  • static이 사용될 수 있는 곳: 멤버변수, 메서드, 초기화 블럭
  • 인스터스에 관계없이 같은 값을 같는다.
class StaticTest {
	static int width = 200; //클래스 변수(static변수)
    
    static { //클래스 초기화 블럭
    	//static 변수의 복잡한 초기화 수행
    }
    
    static int max(int a, int b) { //클래스 메서드(static메서드)
    	return a > b ? a:b;
    }
}

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

  • final이 사용될 수 있는 곳: 클래스, 메서드, 멤버변수, 지역변수
  • 변수에 사용되면 값을 변경할 수 없는 상수가 되며, 메서드에 사용되면 오버라이딩을 할 수 없게 되고 클래스에 사용하면 자신을 확장하는 자손클래스를 정의하지 못하게 된다.
final class FinalTest { //조상이 될 수 없는 클래스
	final int MAX_SIZE = 10; //값을 변경할 수 없는 멤버변수
    
    final void getMaxSize() { //오버라이딩할 수 없는 메서드
    	final int LV = MAX_SIZE; //값을 변경할 수 없는 지역변수
        return MAX_SIZE;
   	}
}

abstract - 추상의, 미완성의

  • 메서드의 선언부만 작성하고 실제 수행내용은 구현하지 않은 추상 메서드를 선언하는데 사용된다.
  • abstract가 사용될 수 있는 곳 - 클래스, 메서드

접근 제어자

  • 멤버 또는 클래스에 사용. 해당하는 멤버 또는 클래스를 외부에서 접근하지 못하도록 제한하는 역할을 한다. (내부에 선언된 데이터를 보호하기 위해서)
  • 접근 제어가 사용될 수 있는 곳 - 클래스, 멤버변수, 메서드, 생성자
제어자같은 클래스같은 패키지자손 클래스전체
publicOOOO
protectedOOOX
(default)OOXX
privateOXXX
  • 캡슐화: 데이터가 유효한 값을 유지하도록, 또는 비밀번호와 같은 데이터를 외부에서 함부로 변경하지 못하도록 하기 위해서 외부로부터의 접근을 제한하는 것


5. 다형성

다형성이란?

  • 여러 가지 형태를 가질 수 있는 능력
  • ex. 조상 타입의 참조변수로 자손 인스턴스를 참조
Tv t = new CaptionTv();
  • 참조변수가 사용할 수 있는 멤버의 개수는 인스턴스의 멤버 개수보다 같거나 적어야 한다.

참조변수의 형변환

  • 자손타입→조상타입 (업캐스팅): 형변환 생략가능
  • 조상타입→자손타입 (다운캐스팅): 형변환 생략불가
  • 참조변수가 참조하고 있는 인스턴스의 자손타입으로 형변환을 하는 것은 허용되지 않음
    ex. car이 조상, fireEngine과 Ambulance가 자손
Car car = null;
FireEngine fe = newFireEngine();
FireEngine fe2 = null;

car = fe; //car = (Car)fe;에서 형변환이 생략됨. 업캐스팅
fe2 = (FireEngine)car; //형변환 생략불가. 다운캐스팅

instanceof연산자

  • 참조변수 + instanceof + 타입(클래스명)
    true: 참조변수가 검사한 타입(클래스명)으로 형변환 가능
    false: 참조변수가 검사한 타입으로 형변환 불가



예제

Q. 오버라이딩의 정의와 필요성에 대해 설명하세요. 그리고 Car 클래스를 상속받는 Bus 클래스에서 run 메소드를 오버라이드 하세요. 오버라이드한 run메소드는 "차가 달리면서 다음 정거장을 안내합니다."라고 출력해야 합니다.

public class Car {
    public void run() {
        System.out.println("Car의 run메소드");
    }
}

/*Bus 클래스 작성*/

A.
오버라이딩이란 조상 클래스로부터 상속받은 메서드를 자손 클래스에 맞게 재정의 하는 것을 말한다. 조상 클래스로부터 상속받은 메서드를 자손 클래스에서 그대로 사용할 수 없는 경우가 많기 때문에 오버라이딩이 필요하다.

public class Bus extends Car {
    public void run() {
		System.out.println("차가 달리면서 다음 정거장을 안내합니다.");
    }
}

0개의 댓글

관련 채용 정보