[필기정리]Day12 - 상속

SW/Java

2020. 6. 25. 15:22

# 상속 : 부모(상위) 클래스의 모든 속성, 메소드를 자식(하위) 클래스가 물려받는 것

 

- 동일표현

  상위클래스(super class), 부모클래스(parents class), 기초클래스(base class) 

  하위클래스(sub class), 자식클래스, 유도클래스(derived class) 

 

ex)

class AAA //상위 클래스
{
	public int num1;
	
	public void printAAA()
	{
		System.out.println("AAA");
	}	
}

class BBB extends AAA // 하위 클래스
{
	public int num2;
	
	public void printBBB()
	{
		System.out.println("BBB");
	}	
}

class ABMain 
{
	public static void main(String[] args)
	{
		BBB bbb = new BBB();
		bbb.num2 = 10;
		bbb.printBBB();
		
		bbb.num1 = 20; //AAA 클래스를 상속 받았기 때문에 num1에 접근 가능
		bbb.printAAA(); // 결과 : AAA
	}
}

 

- 상속을 받은 경우 상위 클래스가 하위 클래스의 객체 주소를 참조할 수 있다.

  하지만 하위 클래스가 역으로 참조는 불가능하다.

 

ex)

ex)
class AAA
{	
}

class BBB extends AAA 
{	
}

class ABMain 
{
	public static void main(String[] args)
	{
		AAA aaa = new BBB(); // 참조 가능 
		BBB bbb = new AAA();  // 결과 : error 발생 
	}
}

 

★ 컴파일러가 가리키는 곳의 객체를 AAA 클래스의 객체라고 생각하기 때문에 에러 발생
   

 

ex)

class AAA
{	
	public int num1;
	public void printAAA()
	{
		System.out.println("AAA");
	}
}

class BBB extends AAA 
{	
	public int num2;
	public void printBBB()
	{
		System.out.println("BBB");
	}
}

class ABMain 
{
	public static void main(String[] args)
	{
		AAA aaa = new BBB();
		aaa.printBBB();
		// ★ 컴파일러가 가리키는 곳의 객체를 AAA 클래스의 객체라고 생각하기 때문에 에러 발생
		      (그림 참조할 것)
		((BBB)aaa).printBBB();
		// 이렇게 변경하면 객체를 참조할 수 있게 된다.
	}
}

 

- 간접적인 상속 클래스도 객체 주소값 참조가 가능하다.

ex)

ex)
class AAA
{	
	public int num1;
	public void printAAA()
	{
		System.out.println("AAA");
	}
}  	

class BBB extends AAA 
{	
	public int num2;
	public void printBBB()
	{
		System.out.println("BBB");
	}
}		

class CCC extends BBB 
{	
	public int num3;
	public void printCCC()
	{
		System.out.println("CCC");
	}
}
class ABMain 
{
	public static void main(String[] args)
	{
		BBB b1 = new BBB();
		b1.num1 = 10;
		b1.printAAA(); //상속하여 가능

		CCC c1 = new CCC();
		c1.num2 = 20; //상속하여 가능
		c1.printBBB();

		c1.num1=30; 
		c1.printAAA();
// AAA클래스의 모든 것을 BBB클래스에 상속했고, BBB클래스를 CCC클래스가 모두 상속 받았기 때문에 가능함 
	}
}
		AAA a1 = new BBB(); // 상위 클래스가 하위 클래스 객체 주소 참조 가능
		BBB b1 = new CCC(); // 마찬가지로 가능함
		AAA a2 = new CCC(); // 간접적으로 CCC가 AAA에 상속받았기 때문에 객체 주소값 참조가능함

 

★ 메소드 오버라이딩 

  상위 클래스 있는 메소드를 하위 클래스가 재정의 하는 것

  메소드 이름, 반환형, 매개변수까지 완벽하게 똑같아야만 한다.

  메소드 오버라이딩을 하게 되면 최종적으로 메소드 오버라이딩된 메소드를 호출하게 된다.

 

ex)

class AAA
{	
	public int num1;
	public void printHi()
	{
		System.out.println("AAA");
	}
}  	

class BBB extends AAA 
{	
	public int num2;
	public void printHi()
	{
		System.out.println("BBB");
	}
}		

class CCC extends BBB 
{	
	public int num3;
	public void printHi()
	{
		System.out.println("CCC");
	}
}

class ABMain 
{
	public static void main(String[] args)
	{
		AAA a1 = new AAA();
		a1. printHi(); // 결과 : AAA
		AAA a2 = new BBB();
		a2. printHi(); // 결과 : BBB
		AAA a3 = new CCC();
		a3. printHi(); // 결과 : CCC
		BBB b1 = new BBB();
		b1. printHi(); // 결과 : BBB
		BBB b2 = new CCC();
		b2. printHi(); // 결과 : CCC

 

- 상속 관계에서도 메소드 오버로딩이 지원된다.

                             ㄴ 메소드 이름은 같으나 매개변수의 개수, 형이 다른 경우!

ex)

class AAA
{	
	public int num1;
	public void printHi()
	{
		System.out.println("AAA");
	}
	public void printBye()
	{
		System.out.println("void");
	}
}  	

class BBB extends AAA 
{	
	public int num2;
	public void printHi()
	{
		System.out.println("BBB");
	}
	public void printBye(int n)
	{
		System.out.println("int");
	}
}		

class CCC extends BBB 
{	
	public int num3;
	public void printHi()
	{
		System.out.println("CCC");
	}
	public void printBye(double n)
	{
		System.out.println("double"); 
	}
}

class ABMain 
{
	public static void main(String[] args)
	{
		CCC c1 = new CCC();
		c1. printBye(); // 결과 : void
		CCC c1 = new CCC();
		c1. printBye(5); // 결과 : int
		CCC c1 = new CCC();
		c1. printBye(3.14); // 결과 : double

 

- 메소드 오버라이딩의 접근제어지시자는 넓혀지는 방향은 가능하나 좁히는 방향을 줄 수 없다.

ex)

class AAA //BBB로 접근제어지시자 메소드 오버라이딩 하는 경우
{	
	private int num1; // 상속받은 메소드에서 private, default, protected, public 가능
	int num1; // 상속받은 메소드에서 default, protected, public 가능
	protected num1; // 상속받은 메소드에서 protected, public 가능
	public num1; // 상속받은 메소드에서 public만 가능
}

 

- 하위 클래스의 생성자에서는 반드시 가장 먼저 상위 클래스의 생성자를 호출해야 한다.

ex)

class Man
{
	public String name;
	Man(String name)
	{
		this.name = name;
	}
}

class BMan extends Man
{
	public String company;
	BMan(String name, String company)
	{
		super(name); //상위 클래스의 생성자를 의미, 
		// 하위 클래스의 생성자에서는 가장 먼저 호출하거나, 호출하는 형태가 되어야 한다(안하면 에러) 
		this.company = company;
	}
	public void printCS()
	{
		System.out.println(super.name+" "+this.company);
		// super와 this 생략 가능
	}
}

class MBMain
{
	public static void main(String[] args)
	{
		BMan b = new BMan("홍길동“, ”삼성“);
	}
}

 

- 접근제어지시자가 private인 경우 아무리 상속 받았어도 바로 접근 불가하다.

  get 메소드를 사용해 간접적으로 접근시켜야 한다.

ex)

class Man
{
	private String name; 
	Man(String name)
	{
		this.name = name;
	}
	public String getName() // 이 메소드를 상속 받기 때문에 이 메소드로 호출하면 된다.
	{
		return name;
	}
}

class BMan extends Man
{
	public String company;
	BMan(String name, String company)
	{
		super(name); //상위 클래스의 생성자를 의미, 
		// ★하위 클래스의 생성자에서는 가장 먼저 호출하거나, 호출하는 형태가 되어야 한다(안하면 에러) 
		this.company = company;
	}
	public void printCS()
	{
		System.out.println(super.name+" "+this.company);
		// super와 this 생략 가능 , private이므로 super.name으로 바로 호출 불가함
		System.out.println(getName()+" "+this.company);
		// 이렇게 상속받은 getName 메소드로 호출해야 에러 발생하지 않는다.
	}
}

class MBMain
{
	public static void main(String[] args)
	{
		BMan b = new BMan("홍길동“, ”삼성“);
	}
}

 

- 생성자를 안만든 경우 자바 컴파일러가 디폴트 생성자를 삽입한다.

  (자바 컴파일러는 생성자는 삽입하지 않으면 자동으로 이러한 형태로 생성자 자동으로 삽입시킴)

ex)

class AAA
{
	AAA(){} // 자동으로 만들어진 생성자
}

class BBB extends AAA
{
	BBB()          /*
	{			자동으로 삽입된 생성자
		super();
	}					*/
}

 

- 상위 클래스에 만든 생성자가 있는 경우 하위 클래스에서 자동 생성자가 있는 경우 에러 발생한다.

ex)

class AAA
{
	int num;
	AAA(int num)
	{
		this.num=num;
	}
}		

class BBB extends AAA - 에러 발생
{
	BBB()          /*
	{			자동으로 삽입된 생성자
		super();
	}					*/
}

 

ex) 메소드 오버로딩으로 만든 예시

class AAA
{
	int num;
	AAA(int num)
	{
		this.num=num;
	}
	AAA(){} // 자동으로 삽입된 생성자
}		

class BBB extends AAA
{
	BBB()          /*
	{			자동으로 삽입된 생성자
		super();
	}					*/
}

 

ex)

class AAA
{
	int num;
	AAA(int num)
	{
		this.num=num;
	}
	AAA(){} // 자동으로 삽입된 생성자
}		

class BBB extends AAA
{
	BBB()          
	{			
		super(); // 자동으로 삽입된 생성자
	}				
}		

class BBB extends AAA
{
	BBB()          
	{			
		super(); // 자동으로 삽입된 생성자
	}				
}

 

//Tip : 반드시 앞이 상위클래스여야 한다.

        상위클래스 변수명 = new 하위클래스

 

- 하위 클래스에서 this.name=name으로 정의 가능하지만 점점 상속받을수록 할 일이 많아지기 때문에

  정의는 본인 클래스에서 해줘야 깔끔하다.

ex)

class Man
{
	String name;
	public Man(String name)
    {
    	this.name=name;
    }
    
	public void tellYourName() 
    { 
    	System.out.println("My name is "+name); 
    }
}

class BusinessMan extends Man
{
	String company; 	// 회사이름
	String position;	// 직급
    
	public BusinessMan(String name, String company, String position)
	{
		super(name); //상위 클래스의 생성자를 가장 먼저 호출한 것
		this.company=company;
		this.position=position;
	}
    
	public void tellYourInfo()
	{
		System.out.println("My company is "+company);
		System.out.println("My position is "+position);
		tellYourName();   	// Man 클래스를 상속했기 때문에 호출 가능!
	}
}

class BasicInheritance
{
	public static void main(String[] args)
	{
		BusinessMan man1
			=new BusinessMan("Mr. Hong", "Hybrid 3D ELD", "Staff Eng.");
		BusinessMan man2
			=new BusinessMan("Mr. Lee", "Hybrid 3D ELD", "Assist Eng.");
	
		System.out.println("First man info..........");
		man1.tellYourName(); // My name is Mr. Hong
		man1.tellYourInfo(); /* My company is Hybrid 3D ELD
				                My position is Staff Eng */			
		
		System.out.println("Second man info..........");
		man2.tellYourInfo(); /* My company is Hybrid 3D ELD
				                My position is Assist Eng.
				                My name is Mr. Lee */	 	
	}
}

 

ex)

class Accumulator
{
	private int val;
	
	Accumulator(int init)
    {
    	val=init;
    }	
	
    protected void accumulate(int num)
	{
		if(num<0)      // 음수는 누적 대상에서 제외!
			return;
		val+=num; 
	}
	
    protected int getAccVal()
    {
    	return val;
    } //getVal이 올바른 표현(책의 예시일 뿐이다)
}

class SavingAccount extends Accumulator
{
	public SavingAccount(int initDep)
	{
		super(initDep);      // 통장개설 시 첫 입금액
	}
	public void saveMoney(int money)
	{
		accumulate(money);
	}
	public void showSavedMoney()
	{
		System.out.print("지금까지의 누적금액: ");
		System.out.println(getAccVal()); // private이기 때문에 엑세스메소드를 사용한 것
	}
}

class PrivateInheritance
{	
	public static void main(String[] args)
	{
		SavingAccount sa=new SavingAccount(1000);
		sa.saveMoney(1000);
		sa.saveMoney(1000);
		sa.showSavedMoney(); // 결과 : 3000	
	}
}

 

ex)

class AAA
{
	public static int num = 5;
}

class BBB extends AAA
{
}

class ABMain
{
	public static void main(String[] args)
	{
		System.out.println(AAA.num);
		System.out.println(BBB.num); // 결과 : 5
	}
}

 

- 스테틱 메소드나 멤버변수도 상속 가능하다.

ex)

class Adder
{
	public static int val=0;
		
	public void add(int num)
	{
		val+=num;
	}
}

class AdderFriend extends Adder
{
	public void friendAdd(int num)
	{
		val+=num; //public이라 바로 접근 가능
	}
	public void showVal()
	{
		System.out.println(val); 
	}
}

class StaticInheritance
{	
	public static void main(String[] args)
	{
		Adder ad=new Adder();
		AdderFriend af=new AdderFriend();
		ad.add(1);
		af.friendAdd(3);
		AdderFriend.val+=5; //하위 클래스의 이름으로 접근, public이라 가능한 것
		af.showVal(); 
	}
}	

 

- 상속이라고 한글로 번역 했으나 확장이라는 개념이 더 맞긴 하다.

  상위 클래스의 요소를 갖고 하위 클래스가 더욱 확장되는 것이기 때문이다.

 

Q. 다음 클래스에 적절한 생성자를 삽입해보자.

그리고 이의 확인을 위한 main 메소드도 적절히 정의해 보자.

class Car	// 기본 연료 자동차
{
	int gasolineGauge;
}

class HybridCar extends Car	// 하이브리드 자동차
{
	int electricGauge;
}

class HybridWaterCar extends HybridCar		// 하이브리드 워터카
{
	int waterGauge;

	public void showCurrentGauge()
	{
		System.out.println("잔여 가솔린 : " + gasolineGauge);
		System.out.println("잔여 전기량 : " + electricGauge);
		System.out.println("잔여 워터량 : " + waterGauge);
	}
}

 

A. 

class Car	// 기본 연료 자동차
{
	int gasolineGauge;
	Car(int gasolineGauge) 
	{
		this.gasolineGauge = gasolineGauge;
	}
}

class HybridCar extends Car	// 하이브리드 자동차
{
	int electricGauge;
	HybridCar(int gasolineGauge, int electricGauge) 
	{
		super(gasolineGauge);
		this.electricGauge = electricGauge;
	}
}

class HybridWaterCar extends HybridCar		// 하이브리드 워터카
{
	int waterGauge;
	HybridWaterCar(int gasolineGauge, int electricGauge, int waterGauge) 
	{
		super(gasolineGauge, electricGauge);
		this.waterGauge = waterGauge;
	}

	public void showCurrentGauge()
	{
		System.out.println("잔여 가솔린 : " + gasolineGauge);
		System.out.println("잔여 전기량 : " + electricGauge);
		System.out.println("잔여 워터량 : " + waterGauge);
	}
}

class CarMain
{
	public static void main(String[] args)
	{
		HybridWaterCar hwCar = new HybridWaterCar(10, 20, 30);
		hwCar.showCurrentGauge(); 
	}
}

 

A. private로 멤버변수를 변경한 경우, 출력값은 동일해야 한다. (get 메소드 사용 예시)

class Car	// 기본 연료 자동차
{
	private int gasolineGauge;
	Car(int gasolineGauge) 
	{
		this.gasolineGauge = gasolineGauge;
	}
	public int getGasolineGauge()
	{
		return gasolineGauge;
	}
}

class HybridCar extends Car	// 하이브리드 자동차
{
	private int electricGauge;
	HybridCar(int gasolineGauge, int electricGauge) 
	{
		super(gasolineGauge);
		this.electricGauge = electricGauge;
	}
	public int getElectricGauge()
	{
		return electricGauge;
	}
}

class HybridWaterCar extends HybridCar		// 하이브리드 워터카
{
	private int waterGauge;
	HybridWaterCar(int gasolineGauge, int electricGauge, int waterGauge) 
	{
		super(gasolineGauge, electricGauge);
		this.waterGauge = waterGauge;
	}

	public void showCurrentGauge()
	{
		System.out.println("잔여 가솔린 : " + getGasolineGauge());
		System.out.println("잔여 전기량 : " + getElectricGauge());
		System.out.println("잔여 워터량 : " + waterGauge);
	}
}

class CarMain
{
	public static void main(String[] args)
	{
		HybridWaterCar hwCar = new HybridWaterCar(10, 20, 30);
		hwCar.showCurrentGauge(); 
	}
}

 

A. private로 멤버변수를 변경한 경우, 출력값은 동일해야 한다. (메소드 오버라이딩 사용 예시)

   메소드 오버라이딩 방법을 사용했을 때 훨씬 더 편리하게 변경이 가능하다.

class Car	// 기본 연료 자동차
{
	private int gasolineGauge;
	Car(int gasolineGauge)
	{
		this.gasolineGauge = gasolineGauge;
	}
	public void showCurrentGauge()
	{
		System.out.println("잔여 가솔린 : " + gasolineGauge);
	}
}

class HybridCar extends Car	// 하이브리드 자동차
{
	private int electricGauge;
	HybridCar(int gasolineGauge, int electricGauge)
	{
		super(gasolineGauge);
		this.electricGauge = electricGauge;
	}
	public void showCurrentGauge()
	{
		super.showCurrentGauge();
		System.out.println("잔여 전기량 : " + electricGauge);
	}
}

class HybridWaterCar extends HybridCar		// 하이브리드 워터카
{
	private int waterGauge;

	HybridWaterCar(int gasolineGauge, int electricGauge, int waterGauge)
	{
		super(gasolineGauge, electricGauge);
		this.waterGauge = waterGauge;
	}

	public void showCurrentGauge()
	{
		super.showCurrentGauge();
		System.out.println("잔여 워터량 : " + waterGauge);
	}
}

class CarMain
{
	public static void main(String[] args)
	{
		HybridWaterCar hwCar = new HybridWaterCar(10, 20, 30);
		hwCar.showCurrentGauge();
	}
}

 

- 자바에서는 생성자가 상속되지 않는다.

ex)

HybridWaterCar hwCar = new HybridWaterCar(10); // 결과 : error

 

# 상속 ≠ 재활용

- 상속을 통해 상속한 클래스와 상속받은 클래스 간의 공통적인 규칙을 생성하기 위해 사용하는 것이다.

  ex) - 참새 - 짹짹

             오리 - 꽥꽥

 

  상속은 처음 설계부터 설정하는 것이지 재활용하는 것이 아니다.

  재활용은 대개 패키지 단위로 이루어진다. ex) 병원 영수증 패키지

  재활용은 클래스 단위로 이루어지지 않는다.

 

is a 관계가 성립하면 상속 관계로 묶을 수 있다.

  ex) notebook is a computer - computer(상위클래스), notebook(하위클래스) 

 

ex)

class Computer
{
	String owner;
	
	public Computer(String name){owner=name;}
	public void calculate()
	{
		System.out.println("요청 내용을 계산합니다.");
	}
}

class NotebookComp extends Computer
{
	int battary;
	
	public NotebookComp(String name, int initChag)
	{
		super(name);
		battary=initChag;
	}	
	public void charging()
	{
		battary+=5;
	}	
	public void movingCal()
	{
		if(battary<1)
		{
			System.out.println("충전이 필요합니다.");
			return;
		}
	
		System.out.print("이동하면서 ");
		calculate(); //상속받아서 호출 가능
		battary-=1;		
	}
}

class TabletNotebook extends NotebookComp
{
	String regstPenModel;
	
	public TabletNotebook(String name, int initChag, String pen)
	{
		super(name, initChag);
		regstPenModel=pen;
	}
	
	public void write(String penInfo)
	{
		if(battary<1)
		{
			System.out.println("충전이 필요합니다.");	
			return;
		}
		
		if(regstPenModel.compareTo(penInfo)!=0)
		{
			System.out.println("등록된 펜이 아닙니다.");
			return;
		}

		System.out.println("필기 내용을 처리합니다.");
		battary-=1;		
	}
}

class ISAInheritance
{
	public static void main(String[] args)
	{
		NotebookComp nc=new NotebookComp("이수종", 5);
		TabletNotebook tn=new TabletNotebook("정수영", 5, "ISE-241-242");
		
		nc.movingCal();
		tn.write("ISE-241-242");
	}
}

 

 

# is a - 상속

   has a - 넓은 의미로 보면 상속일 수 있으나 가급적 멤버변수로 두는 것이 좋다

  둘 다 말이 안되면 절대 상속의 관계로 묶으면 안된다.

  (문법적으로 묶을 수 있지만 논리, 개념적으로 봤을 때는 안 되는 관계이다)

 

ex) 상속예시

class Gun
{
	int bullet;    	// 장전된 총알의 수
	
	public Gun(int bnum){bullet=bnum;}
	public void shut()
	{
		System.out.println("BBANG!");
		bullet--;
	}
}

class Police extends Gun
{
	int handcuffs;	     // 소유한 수갑의 수
	
	public Police(int bnum, int bcuff)
	{
		super(bnum);
		handcuffs=bcuff;
	}
	public void putHandcuff() 
	{
		System.out.println("SNAP!");
		bullet--;
	}
}

class HASInheritance
{
	public static void main(String[] args)
	{
		Police pman=new Police(5, 3);
		pman.shut();
		pman.putHandcuff();
	}
}

 

ex) 멤버변수 예시

class Gun
{
	int bullet;		// 장전된 총알의 수
	
	public Gun(int bnum){bullet=bnum;}
	public void shut()
	{
		System.out.println("BBANG!");
		bullet--;
	}
}

class Police
{
	int handcuffs;	// 소유한 수갑의 수
	Gun pistol;		// 소유하고 있는 권총
	
	public Police(int bnum, int bcuff)
	{
		handcuffs=bcuff;
		if(bnum!=0)
			pistol=new Gun(bnum);
		else
			pistol=null;
	}
	public void putHandcuff() 
	{
		System.out.println("SNAP!");
		handcuffs--;
	}
	public void shut()
	{
		if(pistol==null)
			System.out.println("Hut BBANG!");
		else
			pistol.shut();
	}
}

class HasComposite
{
	public static void main(String[] args)
	{
		Police haveGun=new Police(5, 3);	// 총알 5, 수갑 3
		haveGun.shut();
		haveGun.putHandcuff();
		
		Police dontHaveGun=new Police(0, 3);	// 총알 0, 수갑 3
		dontHaveGun.shut();
	}
}

 

ex)

class Speaker
{
	private int volumeRate;
	
	public void showCurrentState()
	{
		System.out.println("볼륨 크기: "+ volumeRate);
	}
	public void setVolume(int vol)
	{
		volumeRate=vol;
	}
}

class BaseEnSpeaker extends Speaker
{
	private int baseRate;
	
	public void showCurrentState()
	{
		super.showCurrentState(); 
		System.out.println("베이스 크기: "+baseRate);
	}
	public void setBaseRate(int base)
	{
		baseRate=base;
	}
}

class Overriding
{
	public static void main(String[] args)
	{
		BaseEnSpeaker bs=new BaseEnSpeaker(); // 자료형을 Spearker로 바꿔도 가능
		bs.setVolume(10);
		bs.setBaseRate(20); 
		//Speaker로 바꾸는 경우 에러 발생
		 ((BaseEnSpeaker)bs).setBaseRate(20);로 형변환해줘야 함  
		bs.showCurrentState();
	}
}

 

ex)

class AAA
{
	public void rideMethod(){System.out.println("AAA's Method");}
	public void loadMethod(){System.out.println("void Method");}
}

class BBB extends AAA
{
	public void rideMethod(){System.out.println("BBB's Method");}
	public void loadMethod(int num){System.out.println("int Method");}
}

class CCC extends BBB
{
	public void rideMethod(){System.out.println("CCC's Method");}
	public void loadMethod(double num){System.out.println("double Method");}
}

class RideAndLoad
{
	public static void main(String[] args)
	{
		AAA ref1=new CCC();		
		BBB ref2=new CCC();
		CCC ref3=new CCC();
		
		ref1.rideMethod(); // 결과 : CCC's Method
		ref2.rideMethod(); // 결과 : CCC's Method
		ref3.rideMethod();
		
		ref3.loadMethod(); // 결과 : void Method (메소드 오버로딩)
		ref3.loadMethod(1); // 결과 : int Method
		ref3.loadMethod(1.2); // 결과 : double Method
	}
}

 

ex)

문법적으로는 맞지만 이런 식으로 상위 클래스와 하위 클래스의 멤버변수 명을 동일하게 주면 헷갈릴 수 있기 때문에

절대로 상속관계에 있어 멤버변수명을 똑같게 주지 않아야 한다! 주의하기!

class AAA 
{
	public int num=2;
}

class BBB extends AAA
{
	public int num=5;
}

class CCC extends BBB
{
	public int num=7;
}

class ValReDecle
{
	public static void main(String[] args)
	{
		CCC ref1=new CCC();		
		BBB ref2=ref1; //상위클래스가 하위클래스 객체 주소값 참조하는 것으로 가능
		AAA ref3=ref2; // 상위클래스가 하위클래스 객체 주소값 참조하는 것으로 가능
		
		System.out.println("CCC's ref: "+ref1.num);	// 결과 : 7	
		System.out.println("BBB's ref: "+ref2.num);	// 결과 : 5	
		System.out.println("AAA's ref: "+ref3.num); // 결과 : 2
	}
}

 

ex)

class AAA 
{
	public int num=2;
}

class BBB extends AAA
{
	public int num=5;
	public void showSuperNum()
	{
		System.out.println("AAA's num: "+super.num); //결과 : AAA's num: 2
	}
}

class CCC extends BBB
{
	public int num=7;
	public void showAllNums()
	{
		super.showSuperNum();
		System.out.println("BBB's num: "+super.num); // 결과 : BBB's num: 5 	
		System.out.println("CCC's num: "+num); //결과 : CCC's num: 7
	}
}

class ShowAllReDecl
{
	public static void main(String[] args)
	{
		CCC ref=new CCC();
		ref.showAllNums();
	}
}

 

- instanceof 연산자 : 아래 예시에서 boxGoldPaperBox로 형변환이 가능하면 true

                            형변환이 안되면 false를 반환한다.

ex)

class Box
{
	public void simpleWrap(){System.out.println("simple wrap");}
}

class PaperBox extends Box
{
	public void paperWrap() {System.out.println("paper wrap");}
}

class GoldPaperBox extends PaperBox
{
	public void goldWrap() {System.out.println("gold wrap");}
}

class InstanceOf
{
	public static void wrapBox(Box box)
	{
		if(box instanceof GoldPaperBox)
			((GoldPaperBox)box).goldWrap();
		else if(box instanceof PaperBox)
			((PaperBox)box).paperWrap();
		else
			box.simpleWrap();
	}
	
	public static void main(String[] args)
	{
		Box box1=new Box();
		PaperBox box2=new PaperBox();
		GoldPaperBox box3=new GoldPaperBox();
		
		wrapBox(box1); // 결과 : simpleWrap
		wrapBox(box2); // 결과 : paperWrap
		wrapBox(box3); // 결과 : goldWrap
	}
}

 

Q.

폴더에 있는 InstanceOf.javainstanceof 연산자를 사용하지 않는 형태로 변경하고자 한다.

, 클래스의 상속관계를 그대로 유지하면서

(물론 메소드는 추가할 수 있다. 상속 관계만 그대로 유지하면 된다),

instanceof 연산자를 사용하지 않고도 동일한 실행결과를 보일 수 있어야 한다.

참고로 여러분에게 힌트가 될 수 있도록, 변경되어야 할 wrapBox 메소드를 여기 제시하겠다.

public static void wrapBox(Box box)
{
	box.wrap();
}

------------------------------------------------------------

[폴더내용]

class Box
{
	public void simpleWrap(){System.out.println("simple wrap");}
}

class PaperBox extends Box
{
	public void paperWrap() {System.out.println("paper wrap");}
}

class GoldPaperBox extends PaperBox
{
	public void goldWrap() {System.out.println("gold wrap");}
}

class InstanceOf
{
	public static void wrapBox(Box box)
	{
		if(box instanceof GoldPaperBox)
			((GoldPaperBox)box).goldWrap();
		else if(box instanceof PaperBox)
			((PaperBox)box).paperWrap();
		else
			box.simpleWrap();
	}
	
	public static void main(String[] args)
	{
		Box box1=new Box();
		PaperBox box2=new PaperBox();
		GoldPaperBox box3=new GoldPaperBox();
		
		wrapBox(box1);
		wrapBox(box2);
		wrapBox(box3);
	}
}

 

A.

class Box
{
	public void simpleWrap(){System.out.println("simple wrap");}
}

class PaperBox extends Box
{
	public void paperWrap() {System.out.println("paper wrap");}
}

class GoldPaperBox extends PaperBox
{
	public void goldWrap() {System.out.println("gold wrap");}
}

class InstanceOf
{
	public static void wrapBox(Box box)
	{
		box.wrap();
	}
	
	public static void main(String[] args)
	{
		Box box1=new Box();
		PaperBox box2=new PaperBox();
		GoldPaperBox box3=new GoldPaperBox();
		
		wrapBox(box1); 
		wrapBox(box2);
		wrapBox(box3);
	}
}
728x90