객체지향 3대원칙
추상화와 캡슐화
상속
다형성

 

 

 

 

 

 

 

 

상속

 

부모클래스가 가지는 멤버(필드,메소드)를 자식클래스가 물려받아 자신의 멤버인 것처럼 사용할 수 있도록 만든 기술
  • 멤버 외에 타입(부모클래스의 타입) 또한 상속이 된다. (다형성의 토대)
  • 자바는 단일 상속(하나의 클래스만을 부모클래스로 가짐)만 지원 -> 모호성 때문

 

 

상속관계 화살표는 자식에서 부모를 향한 방향이다.

 

 

  • 클래스 간의 상속 시에는 extends 키워드를 사용
public class Academy extends Company{ }

 

 

 

 

 

 

상속의 장단점

 

 

상속의 장점
  • 새로운 클래스를 작성 시 기존에 작성 된 클래스의 재사용 가능
  • 클래스간 계층 관계가 형성되어 다형성 문법의 토대가 됨

 

상속의 단점
  • 부모클래스의 기능 변경 시 자식클래스의 정상적인 동작 유무 예측이 힘듦
  • 자식클래스가 물려받아 사용하는 기능들을 부모클래스에서 변경 시 어려움이 따름
  • 부모클래스로부터 물려받은 기능이 자식클래스에서는 무의미 할 수 있음

 

장단점을 고려해 볼 때 IS-A 관계로 구분되는 경우에만 사용해야 함

 

 

 

 

 

 

IS-A

 

“자식클래스는 (하나의)부모 클래스이다.”의 관계로, 부모클래스의 멤버들을 자식클래스가 상속 받음

 

Circle is a Shape. -> Circle 클래스는 하나의(일종의) Shape 클래스이다.

 

자식클래스는 일종의/하나의 부모클래스이다.
-> 재사용성이 늘어나며 상속의 단점으로 여겨지는 부분이 상쇄될 수 있음

 

 

 

class Application
public class Application {

	public static void main(String[] args) {
		
		Car car = new Car();

		car.soundHorn();
		car.run();
		car.soundHorn();
		car.stop();
		car.soundHorn();
		
//		Car 클래스의 기본 생성자 호출됨...
//		주행중이 아닌 상태에서는 경적을 울릴 수 없습니다.
//		자동차가 달립니다.
//		빵!빵!
//		자동차가 멈춥니다.
//		주행중이 아닌 상태에서는 경적을 울릴 수 없습니다.
		
		
		
		
		/* 소방차, 레이싱 카는 모두 자동차이다.
		 * 하지만 모든 자동차는 소방차 혹은 레이싱카가 아니다.
		 * 
		 * FireCar is a Car(o) / Car is a FireCar(x)
		 * RacingCar is a Car(o) / Car is a RacingCar(x)
		 * 
		 * 이러한 관계가 성립되는 것을 IS-A관계라고 한다.
		 * IS-A 관계가 성립이 되는 경우에 상속을 사용할 수 있다.
		 * 
		 * */
		
		
		FireCar fireCar = new FireCar();
		/* 정말 car의 기능들을 쓸 수 있는 지 확인 */
		
		fireCar.soundHorn();
		fireCar.run();
		fireCar.soundHorn();
		fireCar.stop();
		fireCar.soundHorn();
		
//		Car 클래스의 기본 생성자 호출됨...
//		FireCar 클래스의 기본 생성자 호출됨...
//		주행중이 아닌 상태에서는 경적을 울릴 수 없습니다.
//		자동차가 달립니다.
//		빵!빵!
//		자동차가 멈춥니다.
//		주행중이 아닌 상태에서는 경적을 울릴 수 없습니다.
		
		
		
		/* FireCar 클래스에는 아무것도 작성하지 않았지만 Car 클래스가 가진 메소드를
		 * 전부 사용할 수 있다. 하지만 private 멤버는 접근이 불가능하다.  
		 * 아래 예시는 private이라 접근 불가
		 * */
		
//		fireCar.runningStatus;
//		fireCar.isRunning();
		
		
		
		// 오버라이딩 이후 콘솔 출력
//		Car 클래스의 기본 생성자 호출됨...
//		FireCar 클래스의 기본 생성자 호출됨...
//		소방차가 앞으로 갈 수 없습니다~ 비키세요~
//		자동차가 달립니다.
//		빠아아아앙ㅇ~~!!! 빠앙ㅇ아아아아앙~~~!!!!!!
//		자동차가 멈춥니다.
//		소방차가 앞으로 갈 수 없습니다~ 비키세요~

		
		
		
		fireCar.sprayWater();
		// car.sprayWater();
		// fireCar에만 있기 때문에 부모클래스에서는 사용할 수 없는 기능이다.
		
		
		
		/* 이렇게 상속은 부모가 가진 멤버를 사용하면서 확장까지 가능하도록 해 두었다.
		 * car인스턴스로는 fireCar 가 가진 기능을 사용할 수 없다.
		 * 자식은 부모 멤버에 접근해서 자신의 것처럼 사용 가능하지만, 반대의 경우는 허용하지 않는다.
		 *  */
		
		
		
		
		
		RacingCar racingCar = new RacingCar();
		
		racingCar.soundHorn();
		racingCar.run();
		racingCar.soundHorn();
		racingCar.stop();
		racingCar.soundHorn();
		
//		Car 클래스의 기본 생성자 호출됨... 	// 컴파일러가 묵시적으로 호출
//		RacingCar 클래스 기본 생성자 호출됨...
//		주행중이 아닌 상태에서는 경적을 울릴 수 없습니다.
//		자동차가 달립니다.
//		빵!빵!
//		자동차가 멈춥니다.
//		주행중이 아닌 상태에서는 경적을 울릴 수 없습니다.
		
		// 부모클래스의 기본 생성자는 자식 클래스의 메소드 생성시 가장먼저 호출이 된다.
		// 명시적으로 쓰지않더라도 컴파일러가 묵시적/자동적으로 추가하기 때문에 
		// 자동으로 출력된다.
		
		
	}

}

 

 

class Car
public class Car {

	
	/* 자동차의 달리는 상태를 확인할 수 있는 필드 */
	private boolean runningStatus;
	
	
	/* 기본생성자 */
	public Car() {
		System.out.println("Car 클래스의 기본 생성자 호출됨...");
	}
	
	
	/* 자동차의 기본적인 달리는 기능 */
	public void run() {
		runningStatus = true;
		System.out.println("자동차가 달립니다.");
	}
	
	
	/* 자동차의 기본적인 경적을 울리는 기능 */
	public void soundHorn() {
		
		/* 자동차는 주행 중인 상태일 때 기본적인 경적을 울리는 기능을 수행할 수 있다. */
		if (isRunning()) {
			System.out.println("빵!빵!");
			
		} else {
			System.out.println("주행중이 아닌 상태에서는 경적을 울릴 수 없습니다.");
			
		}
	}
	
	//private boolean isRunning() {
	protected boolean isRunning() {
		
		/*자동차의 주행중 상태를 반환하는 기능을 수행*/
		return runningStatus; 
	}
	
	/* 자동차의 기본적인 멈추는 기능 */
	public void stop() {
		runningStatus = false;
		System.out.println("자동차가 멈춥니다.");
	}
	
}

 

 

class FireCar extends Car
public class FireCar extends Car{

	
	
	/* Car 클래스를 부모클래스로 FireCar 클래스를 자식 클래스로 사용할 것이다.
	 * 클래스 선언부에 extends Car 를 추가해서 Car 클래스를 상속 받을 것이다.
	 * public class FireCar extends Car
	 * 
	 * 1. 그러면 FireCar 클래스는 부모클래스인 Car가 가지고 있는 모든 멤버를 상속 받는다.
	 * 2. 하지만 부모클래스의 생성자는 상속받지 못한다.
	 * 3. 또한 부모가 가지고있는 private 멤버는 접근이 불가능하다.
	 * 
	 * 자바에서 상속은 기본적으로 부모가 가진 멤버를 자식이 사용할 수 있는 것이지만
	 * 더 나아가서 부모클래스의 확장(extend)이라는 개념을 가진다.
	 * 추가적인 자신의 멤버 작성이 가능하며 메소드 재정의(overriding)라는 기술을 이용해서
	 * 부모가 가진 메소드를 재정의 하는 것도 가능하다.
	 * 
	 * */
	
	
	
	
	/* 기본 생성자 */
	public FireCar() {
		
		/* 모든 생성자에는 맨 첫줄에 super() 클래스를 컴파일러가 자동추가한다.
		 * 부모의 기본 생성자를 호출하는 구문이다.
		 * 해당 생성자가 호출 될 시 가장 먼저 Car 클래스 호출 내용이 출력 될 것이다. 
		 * 명시적, 묵시적(안써도 컴파일러가 자동추가) 전부 가능하다. */
		super(); 	
		
		System.out.println("FireCar 클래스의 기본 생성자 호출됨...");
		
	}
	
	
	
	
	
	/* 오버라이딩 */
	
	/* 소방차의 경적 소리가 너무 작으므로 조금 더 크게 키워보자
	 * 경적 소리를 내는 용도의 메소드 선언부는 그대로 두되 소방차 쪽에서 재정의 해 볼 것이다. */
	
	/* @Override 어노테이션 
	 * JDK 1.5 부터 추가된 문법으로 오버라이딩 성립 요건을 체크하여 성립되지않는 경우
	 * 컴파일 에러를 발생시킨다. (오버라이딩이 정상적으로 작성된 것인지를 체크해주는 기능)
	 * 에러 : 철자가 틀리는 등
	 * */
	
	
	
	@Override //부모가 가진 기능을 자식이 고쳐서 사용하고 싶을때 재정의하는 것
	public void soundHorn() {
		
		/* 부모가 가지고 있는 멤버인 isRunning() 메소드를 사용해야
		 * 주행중인 상태를 확인할 수 있으므로 메소드 접근 제한자를  
		 * private -> protected 로 변경*/
		
		if(isRunning()) {
			System.out.println("빠아아아앙ㅇ~~!!! 빠앙ㅇ아아아아앙~~~!!!!!!");
		
		} else {
			System.out.println("소방차가 앞으로 갈 수 없습니다~ 비키세요~");
			
		}
		
	}
	
	
	
	
	/* 부모클래스에는 없지만 자식클래스에는 있는 기능 추가
	 * 물을 뿌리는 기능을 제공 */
	
	public void sprayWater() {
		System.out.println("불난 곳을 발견했습니다. 물을 뿌립니다 =======>>>");
	}
	
	
}

 

 

class RacingCar extends Car
public class RacingCar extends Car {

	
	
	
	/* 기본 생성자 */
	
	public RacingCar() {
		System.out.println("RacingCar 클래스 기본 생성자 호출됨...");
		
	}
	
	
	
	
	
	
	/* 부모로부터 한꺼번에 상속받은 기능이지만 
	 * 레이싱카의 적합하지않은 기능인 경적소리, 달리는 기능등을 수정하고싶다. */
	
	@Override
	public void soundHorn() {
		/* 레이싱카는 경적을 울리지 않는다. */
		System.out.println("레이싱 카는 경적을 울리지 않습니다. (조용...)");
	}
	
	@Override
	public void run() {
		System.out.println("레이싱카가 전속력으로 질주합니다!!!!!!!!!!");
	}
	
//  오버라이딩 후 결과값 출력	
//	Car 클래스의 기본 생성자 호출됨...
//	RacingCar 클래스 기본 생성자 호출됨...
//	레이싱 카는 경적을 울리지 않습니다. (조용...)
//	레이싱카가 전속력으로 질주합니다!!!!!!!!!!
//	레이싱 카는 경적을 울리지 않습니다. (조용...)
//	자동차가 멈춥니다.
//	레이싱 카는 경적을 울리지 않습니다. (조용...)
	
	
}

 

 

 

 

 

 

 

 

 

 

 

super와 super()

 

super
  • super( )와 소괄호가 안붙었다는 차이점이있으므로 구분해서 기억해야한다.
  • 부모클래스의 인스턴스 주소를 보관하는 레퍼런스 변수
  • 자식클래스 내의 모든 생성자와 메소드 내에서 부모클래스의 레퍼런스 변수를 사용할 수 있음

 

super( )
  • 부모 생성자를 호출하는 구문으로 매개변수의 타입, 개수, 순서가 일치하는 부모의 생성자를 호출하게 됨
  • this( )는 해당 클래스의 생성자를 호출하는 구문이다.
  • super( )는 부모클래스가 가지는 private 생성자를 제외한 나머지 생성자를 호출하는 구문이다.

 

 

 

 

class Application
public class Application {

	public static void main(String[] args) {

		/* ProductDTO 기본 생성자로 인스턴스 생성 후 정보 출력 */
		ProductDTO product1 = new ProductDTO();
		System.out.println(product1.getInformation());
		
		/* ProductDTO의 모든 필드를 초기화하는 생성자로 인스턴스 생성 후 정보 출력 */
		ProductDTO product2 = new ProductDTO("S-01234", "삼성", "갤럭시Z폴드1", 2398000, new java.util.Date());
		System.out.println(product2.getInformation());
		
		/* ComputerDTO 기본 생성자로 인스턴스 생성 후 정보 출력 */
		ComputerDTO computer1 = new ComputerDTO();
		System.out.println(computer1.getInformation());
		
		/* ComputerDTO의 모든 필드를 초기화하는 생성자로 인스턴스 생성 후 정보 출력 */
		ComputerDTO computer2 = new ComputerDTO("퀼컴 스냅드래곤", 512, 12, "안드로이드");
		System.out.println(computer2.getInformation());
		
		/* ComputerDTO의 부모 필드로 함께 초기화하는 생성자로 인스턴스 생성 후 정보 출력 */
		
		ComputerDTO computer3 = new ComputerDTO("S-01234", "삼성", "갤럭시Z폴드1", 2398000, new java.util.Date(),
												"퀼컴 스냅드래곤", 512, 12, "안드로이드");
		System.out.println(computer3.getInformation());
		
		
		/* 항상 super()로 부모생성자를 먼저 호출해야 한다. */
		
		
		
		
		
	}

}

 

 

class ProductDTO
import java.util.Date;

public class ProductDTO {

	
	
	/* 관리하려는 상품의 속성을 추상화해서 DTO 클래스를 만든다. */
	private String code;	// 상품코드
	private String brand; 	// 제조사
	private String name;	// 상품명
	private int price;		// 가격 
	private java.util.Date manufacturingDate; 	// 제조일자
	
	
	
	
	
	/* 기본 생성자 */	
	public ProductDTO() {
		System.out.println("ProductDTO 클래스의 기본 생성자 호출함...");
	}

	
	
	
	
	
	/* 모든 필드를 초기화 하는 생성자 */
	public ProductDTO(String code, String brand, String name, int price, Date manufacturingDate) {
		/* 아무 클래스도 상속받지 않았는데 super() 가 호출되는 이유
		 * java.lang.Object 클래스의 생성자가 호출 된 것이다.
		 * 모든 클래스는 Object 클래스의 후손이기 때문이다. */
		
		
		super();	
		// extends 를 선언하지않았는데 생겼다. 무엇을 의미하는 것일까?
		// Every class has {@code Object} as a superclass.
		// ProductDTO extends Object 라 작성하지않더라도 컨파일러가 자동으로 입력해준다.
		// 모든 클래스는 오브젝트 클래스의 자식/후손 이다.
		
		this.code = code;
		this.brand = brand;
		this.name = name;
		this.price = price;
		this.manufacturingDate = manufacturingDate;
		
		System.out.println("ProductDTO 클래스의 매개변수 있는 생성자 호출함...");
	}





	
	
	/* getters/setters 작성하기 */
	
	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getBrand() {
		return brand;
	}

	public void setBrand(String brand) {
		this.brand = brand;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getPrice() {
		return price;
	}

	public void setPrice(int price) {
		this.price = price;
	}

	public java.util.Date getManufacturingDate() {
		return manufacturingDate;
	}

	public void setManufacturingDate(java.util.Date manufacturingDate) {
		this.manufacturingDate = manufacturingDate;
	}
	
	
	
	
	/* 모든 필드 값을 문자열로 반환하는 메소드 */
	public String getInformation() {
		return "ProductDTO [code=" +code + ", brand=" + brand + ", name=" + name 
				+ ", price=" + price + ", manufacturingDate=" + manufacturingDate + "]";
	}
	
	
}

 

 

 

 

class ComputerDTO extends ProductDTO
import java.util.Date;

public class ComputerDTO extends ProductDTO{

	/* ComputerDTO 클래스는 하나의 상품이다. (IS-A)
	 * ProductDTO클래스를 상속받아 작성할 것이다.
 	 *	(단, 생성자는 상속받지않으며 private에는 직접접근 불가)
	 *  */
	
	
	
	/* ComputerDTO가 가지는 추가적인 속성을 필드로 작성한다. */
	private String cpu;
	private int hdd;
	private int ram;
	private String operationSystem;
	
	
	
	
	/* 기본 생성자 */
	public ComputerDTO() {
		System.out.println("ComputerDTO클래스의 기본 생성자 호출함...");	
	}
	/* 자식클래스의 기본 생성자를 생략하면 부모 클래스의 기본생성자 호출에 오류를 만든다.
	 * 자식클래스의 기본생성자는 필수로 작성한다. */

	
	
	

	/* 모든 필드를 초기화 하는 생성자 */
	public ComputerDTO(String cpu, int hdd, int ram, String operationSystem) {

		/* 부모 클래스의 기본 생성자 호출 */		
		super();
		
		this.cpu = cpu;
		this.hdd = hdd;
		this.ram = ram;
		this.operationSystem = operationSystem;
		
		System.out.println("ComputerDTO클래스의 모든 필드를 초기화 하는 생성자 호출함...");
	}
	// 컴퓨터와 관련된 값들은 초기화 하지만, 부모클래스 쪽의 생성자들은 초기화되지않은 
	// 기본값만을 가지고 있을 것이다. 







	
	
	
	
	
	
	/* 부모의 필드도 모두 초기화하는 생성자 */
	/* 우클릭 - source - Generate Constructor from Super class */
	public ComputerDTO(String code, String brand, String name, int price, Date manufacturingDate,
			String cpu, int hdd, int ram, String operationSystem) {
		
		
		/* 부모의 모든 필드를 초기화하는 생성자로 ProductDTO 클래스가 가진 필드를 초기화 할 값 전달 
		 * 반드시 첫 줄에 생성자를 호출해야 오류가 나지않는다. */
		super(code, brand, name, price, manufacturingDate);
	
		// this(cpu, hdd, ram, operationSystem);
		// 생성자 안에서 다른 생성자를 호출할때는 무조건 윗줄에 작성해야 하기에 컴파일 에러가 생긴다.
		
		
		
		
		/* 위와 같이 작성하면 this()로 다시한번 생성자를 호출하게 되기 때문에
		 * 생성자 두 번 호출은 허용되지 않는다.
		 *  */
		this.cpu = cpu;
		this.hdd = hdd;
		this.ram = ram;
		this.operationSystem = operationSystem;
		
		System.out.println("ComputerDTO 클래스의 부모필드도 초기화하는 생성자 호출함...");
	}




	
	
	
	
	

	
	
	/* getters/setters 작성하기 */
	/* 부모 필드의 메소드에 대해서는 자신의 것처럼 사용 가능하므로 따로 작성할 필요가 없다.
	 * 자식 클래스에 추가된 필드에 대해서만 작성한다.  */
	
	

	public String getCpu() {
		return cpu;
	}


	public void setCpu(String cpu) {
		this.cpu = cpu;
	}


	public int getHdd() {
		return hdd;
	}


	public void setHdd(int hdd) {
		this.hdd = hdd;
	}


	public int getRam() {
		return ram;
	}


	public void setRam(int ram) {
		this.ram = ram;
	}


	public String getOperationSystem() {
		return operationSystem;
	}


	public void setOperationSystem(String operationSystem) {
		this.operationSystem = operationSystem;
	}
	

	
	
	
	/* 모든 필드값을 문자열로 반환하는 메소드 */
		@Override
		public String getInformation() {
	
		/* 부모 클래스에서 작성한 getter를 이용해서 부모 필드가 
		 * 가지고 있는 값도 한번에 문자열 합치기를 한다. 
		 * 부모가 가진 멤버는 super.와 this. 둘다 사용이 가능하다.
		 * 하지만 코드의 의미를 명확히 하기 위해 super. 를 사용하는 것이 좋다. 
		 * */
			
//		return "ComputerDTO ["
//				+ "code=" + super.getCode() 
//				+ ", brand=" + super.getBrand()
//				+ ", name=" + super.getName()
//				+ ", price=" + super.getPrice()
//				+ ", manufacturingDate=" + super.getManufacturingDate()
			//super.getInformation() 한줄로 단축할 수도 있다. 
			
//				
//				+ ", cpu=" + this.cpu
//				+ ", hdd=" + this.hdd
//				+ ", ram=" + this.ram
//				+ ", operationSystem=" + this.operationSystem
//				+ "]";
//	
	
			
		/* super.getInformation() : 정상적으로 부모의 메소드 호출
		 * this.getInformation() : 재귀 호출이 일어나며 StackOverflowError 발생
		 * getInformation() : this. 이 자동 추가되어 재귀호출이 일어남
		 * java.lang.StackOverflowError
		 *  */	
		/* 부모의 getInformation 을 호출하여 코드 단축하기 */
		return super.getInformation() //컴퓨터의 getInformation과 구분해야 한다. 
				+ "ComputerDTO ["
				+ ", cpu=" + this.cpu
				+ ", hdd=" + this.hdd
				+ ", ram=" + this.ram
				+ ", operationSystem=" + this.operationSystem
				+ "]";
			
			
	// this.code로는 작성하지 못한다. 왜냐? private이기 떄문
	
	
	
		}
	
	
}

 

상속에서 부모생성자가 먼저 호출이 되어야지만 자식 생성자가 호출될 수 있다. 

 

 

 

 

 

 

 

 

 

오버라이딩

 

오버라이딩(Overriding)이란?
  • 부모클래스에서 상속받은 메소드를 자식클래스가 재정의하여 사용하는 것

 

성립조건
  • 1. 메소드 이름 동일
  • 2. 메소드 리턴 타입 동일
  • 3. 매개변수의 타입, 개수, 순서가 동일
  • 4. private 메소드는 오버라이딩 불가능
  • 5. final 키워드가 사용된 메소드는 오버라이딩 불가능
  • 6. 접근제한자는 부모 메소드와 같거나 더 넓은 범위여야 함
  • 7. 예외처리는 같은 예외이거나 더 구체적(하위)인 예외를 처리해야 함

 

 

 

 

 

 

 

 

오버라이딩과 오버로딩

 

오버로딩은 매개변수만이 영향을 미친다.

 

 

 

오버라이딩 테스트 : class SuperClass
	/* 부모클래스를 의미 */
public class SuperClass {

	/* 오버라이딩 성립 요건에 대해서 알아보자
	 * 오버라이딩이란?
	 * 부모클래스(SuperClass)에서 상속받은 메소드를 자식클래스(SubClass)
	 * 에서 재정의하여 사용하는 것이다. */
	
	
	/* 오버라이팅 테스트를 위한 기준이 되는 메소드 */
	public void method(int num) {}
	
	private void privateMethod() {}
	
	public final void finalMethod() {}
	
	protected void protectedMethod() {}
}

 

 

 

오버라이딩 테스트 : class SubClass
	/* 자식클래스를 의미 */
public class SubClass extends SuperClass {

	/* extends SuperClass를 추가해야 오버라이딩 가능하다. */
	
	
	/* 부모 클래스에서 작성한 메소드를 그대로 가져오면 정상적으로 오버라이딩 되었다.
	 * 1. 메소드 이름 변경 하면 에러발생
	 * 2. 메소드 리턴 타입 변경 하면 에러발생
	 * 3. 매개변수 갯수나 타입 변경시 에러 발생
	 * 
	 *  */
	
	@Override 	//어노테이션
	public void method(int num) {}
	// 1. The method method1(int) of type SubClass must 
	// override or implement a supertype method
	// 2. The return type is incompatible with SuperClass.method(int)
	
	
	
	
	/* 4. private 메소드는 오버라이딩 불가 */
	
	// @Override 
	// private void privateMethod() {}
	// The method privateMethod() of type 
	// SubClass must override or implement a supertype method
	
	
	
	
	
	/* 5. final 메소드는 오버라이딩 불가 */
	
	// @Override 
	// public final void finalMethod() {}
	// Cannot override the final method from SuperClass
	// 파이널 메소드는 재정의할 수 없다. 
	
	// final은 어디에 붙을 수 있을까? 
	// : 지역변수, 필드, 메소드(오버라이딩불가의미), 클래스(상속 불가를 의미)
	// The type SubClass cannot subclass the final class SuperClass
	
	
	
	
	
	/* 6. 부모메소드 접근 제한자와 같거나 더 넓은 범위로만 오버라이딩 가능
	 * 더 좁은 범위의 접근제한자로 변경 불가능하다. */
	
	// @Override 
	// void protectedMethod() {}
	// 넓이 큰 순위대로 public > protected > default > private
	
	// @ Override 
	// protected void protectedMethod() {} 	// 같은 범위로 가능
	
	@ Override 
	public void protectedMethod() {}		// 더 넒은 범위로 가능
	

	
	
	/* 클래스에도 final 키워드를 넣을 수 있는데
	 * final 키워드를 추가하면 상속 불가의 의미를 가진다. 
	 *  */
	
	
	
	
	
	
}

 

 

 

 

 

 

 

 

 

 

 

학습점검

더보기

✅ 클래스의 상속에 대해 이해할 수 있다.
✅ 상속의 목적에 대해 이해할 수 있다.
✅ 상속의 장단점에 대해 이해할 수 있다.
✅ 상속의 특징에 대해 이해할 수 있다.
✅ super에 대해 이해할 수 있다.
✅ 오버라이딩에 대해 이해할 수 있다.
✅ 오버로딩과 오버라이딩의 차이에 대해 이해할 수 있다.

 

 

 

 

 

 

 

 

 

'Programming > JAVA' 카테고리의 다른 글

자바 API  (0) 2022.01.06
다형성  (0) 2022.01.05
객체 배열  (0) 2022.01.03
클래스와 객체(3)  (0) 2021.12.30
클래스와 객체(2)  (0) 2021.12.29

+ Recent posts