5장_상속과 다형성_중간

IkSun·2023년 4월 17일

⏹ 상속

  • 상속
    • 부모 클래스에서 만들어진 특성 (필드, 메소드)을 자식 클래스가 물려받음
    • 부모 클래스, 슈퍼 클래스(super class)
      • 특성을 물려주는 상위 클래스
    • 자식 클래스, 서브 클래스(sub class)
      • 특성을 물려 받는 하위 클래스
      • 슈퍼 클래스에 자신만의 특성(필드, 메소드)추가
      • 슈퍼 클래스의 특성(메소드)을 수정 : 구체적으로 오버라이딩이라고 부름
  • 슈퍼 클래스에서 하위 클래스로 갈수록 구체적
    • 예) 폰 -> 모바일폰 -> 뮤직폰
  • 상속을 통해 간결한 서브 클래스 작성
    • 동일한 특성을 재정의할 필요가 없어 서브 클래스가 간결해짐

⏹ 클래스 상속과 객체

  • 상속 선언 : extends

    • Extends 키워드 사용 : 슈퍼 클래스(부모 클래스)를 확장한다는 개념
  • 자바 상속의 특징

    • 다중 상속을 지원하지 않음 : 다수개의 클래스를 상속 받지 못함(부모는 오직 하나)
    • 인터페이스(정의가 없는 껍데기) 개념이 편법으로되어 있는것으로 여러개 존재 할순있기함.
    • 상속 횟수는 무제한
    • 모든 클래스는 상속의 최상위 조상 클래스인 java.lang.Object 를 상속받는다.
    • 자바 컴파일러에 의해 자동으로 이루어짐
      public class Person { ... }
      public class Student extends Person { ... } //Person 을 상속받는 클래스 student 선언
      public class StudentWorker extends Students { ... } //Student 를 상속받는 StudentWorker 선언
  • 클래스 상속 만들기

    • (x,y) 의 한 점을 표현하는 Point 클래스와 이를 상속받아 컬러 점을 표현하는 ColorPoint 클래스를 만들자.

      class Point{
      	int x,y; //한 점을 구성하는 x,y 좌표
      	public void set(int x, int y) { //멤버변수와 매개변수의 이름이 같아 this 사용
      		this.x = x;
      		this.y = y;
      	}
      	public void showPoint() { //점의 좌표 출력
      		System.out.println("(" + x + "," + y + ")");
      	}
      }
      //Point를 상속받은 ColorPoint 선언
      class ColorPoint extends Point {
      	private String color; //점의 색
      	public void setColor(String color) {
      		this.color = color; 
      	}
         // 컬러 점의 좌표 출력
      	public void showColorPoint() {
      		System.out.print(color);
      		showPoint(); //Point 클래스의 showPoint() 호출
      	}
      }
      public class ColorPointEx {
      
      	public static void main(String[] args) {
      		// TODO Auto-generated method stub
      		Point p = new Point(); //Point 객체 생성
      		p.set(1, 2);	//Point 클래스 set() 호출
      		p.showPoint();
      		
      		ColorPoint cp = new ColorPoint(); //ColorPoint 객체 및 참조 변수 cp 로 관리
      		cp.set(3, 4); //Point의 set() 호출
      		cp.setColor("red"); //ColorPoint 의 setColor() 호출
      		cp.showColorPoint(); //컬러와 좌표 출력
      	}
      }
      //result
      //(1,2)
      //red(3,4)


⏹ 상속과 접근 지정자

  • 자바의 접근 지정자 4가지 : public, private, protected, default

    • 상속관계에서 주의
      • private 은 자식에서 접근 불가
      • protected 는 자식에서 접근 가능
  • 부모 클래스의 private 멤버

    • 다른 모든 클래스의 접근을 허용하지 않는다.
    • 클래스 내의 멤버들에게만 접근 허용
  • 부모 클래스의 default 멤버

    • 같은 패키지 내의 모든 클래스가 default 멤버에 접근 가능
    • 다른 패키지에 있으면 접근 불허
  • 부모 클래스의 public 멤버

    • 다른 모든 클래스가 접근 가능
  • 부모 클래스의 protected 멤버

    • 같은 패키지 내의 모든 클래스가 protected 멤버에 접근 가능
    • 다른 패키지에 있어도 자식 클래스는 protected 멤버에 접근 가능

⏹ 서브 클래스/슈퍼 클래스의 생성자 호출 및 실행

  • new 에 의해 자식 클래스의 객체가 생성될 때
    • 부모 클래스 생성자와 자식 클래스 생성자 모두 실행됨
    • 호출 순서
      • 자식 클래스의 생성자가 먼저 호출되고, 자식 클래스의 생성자가 실행하기 전 부모 클래스의 생성자 호출
    • 실행 순서
      • 부모 클래스의 생성자가 먼저 실행된 후 자식 클래스의 생성자 실행
  • class A {
    	public A() {
    		System.out.println("생성자A");
    	}
        public A(int x) { ... }
    }
    class B extends A {
    	public B() {
        	//super();
    		System.out.println("생성자B");
    	}
    }
    class C extends B {
    	public C() {  //
        	//super(); 부모 클래스 기본 생성자 호출! (없으면 컴파일러가 자동 추가)
    		System.out.println("생성자C");
    	}
    }
    public class ConstructorEx {
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		C c;
    		c = new C();  //생성자 호출 1번
    	}
    }
    //result
    //생성자A
    //생성자B
    //생성자C

⏹ 자식 클래스에서 부모 클래스의 생성자 선택

  • 상속 관계에서의 생성자
    • 부모 클래스와 자식 클래스 각각 여러 생성자 작성 가능
  • 자식 클래스 생성자 작성 원칙
    • 자식 클래스 생성자에서 부모 클래스 생성자 하나 선택
  • 자식 클래스에서 부모 클래스의 생성자를 선택하지 않는 경우
    • 컴파일러가 자동으로 부모 클래스의 기본 생성자를 선택
  • 자식 클래스에서 부모 클래스의 생성자를 선택하는 방법
    • super() 이용

      슈퍼 클래스의 기본 생성자가 자동 선택

      자식 클래스의 기본 생성자에 대해서 부모 클래스의 기본 생성자와 자동으로 짝 지어짐.

      슈퍼 클래스의 기본 생성자가 없어 오류 난 경우

      컴파일러에 의해 클래스 B 에 super() 가 자동 추가되어, 부모 클래스 A의 기본 생성자 A() 를 찾아가는데, 부모 클래스에는 기본 생성자에 대한 정의가 없음

      서브 클래스에 매개변수를 가진 생성자

      서브 클래스의 생성자가 슈퍼 클래스의 생성자를 선택하지 않은 경우
      - super(); 코드가 없으면 맨 위에 자동 추가

      실행 결과

      생성자A
      매개변수생성자B

⏹ super()

  • super()
    • 자식 클래스에서 명시적으로 부모 클래스의 생성자를 선택 호출할 떄 사용
    • 사용 방식
      • super(parameter);
      • 자식 클래스에서 명시적으로 부모 클래스의 생성자 선택 호출
      • 인자를 이용하여 부모 클래스의 적당한 생성자를 호출
      • 반드시 자식 클래스 생성자 코드의 제일 첫 라인에 와야한다.
  • super() 를 이용한 사례
    • 자동으로 추가되는 super() 가 아닌, 내부에서 super(x); 코드 작성
    • 부모 클래스의 '정수 인자 1개가 있는 생성자' 가 호출됨
  • super() 를 이용하여 ColorPoint 클래스의 생성자에서 슈퍼 클래스 Point 의 생성자를 호출하는 예
  • class Point {
    	private int x, y;  //한 점을 구성하는 x,y 좌표
    	public Point() {
    		this.x = this.y = 0;
    	}
    	public Point(int x, int y) {
    		this.x =x;
    		this.y =y;
    	}
    	public void showPoint() {  //점의 좌표 출력
    		System.out.println("(" + x + ", " + y + ")");
    	}
    }
    class ColorPoint extends Point {
    	private String color;  //점의 색
    	public ColorPoint(int x, int y, String color) {
    		super(x,y);  //Point 의 생성자 Point(x,y) 가 호출하여, x=5, y=6 전달
    		this.color = color;
    	}
    	public void showColorPoint() {
    		System.out.print(color);
    		showPoint();
    	}
    }
    public class SuperEx {
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		ColorPoint cp = new ColorPoint(5, 6, "blue"); //ColorPoint(int x, int y, String color) 생성자가 자동 호출
            											  //x=5, y=6, color="blue" 전달
    		cp.showColorPoint();   //Point 클래스의 showPoint() 호출
    	}
    }
    //result
    //blue(5,6)

⏹ 업캐스팅

생물을 넣는 박스에 코끼리나 사람을 넣고 박스 앞에 생물을 가리키는 팻말을 사
용해도 무방하다. 왜냐하면, 사람은 생물을 상속 받았기 때문이다.

  • 자식 클래스의 객체는

    • 부모 클래스의 멤버를 모두 가지고 있다.
    • 부모 클래스의 객체로 취급할 수 있다.
      • '사람은 생물이다' 의 논리와 같음
  • 업캐스팅이란?

    • 자식 클래스 객체를 부모 클래스 타입으로 타입 변환 (상속에서만 가능)
    • class Person { ... }
       class Student extends Person { ... }
       
       Student s = new Student();
       Person p = s; //업캐스팅. 자동 타입 변환 (사람 s 은 생물 p 이다)
  • 업캐스팅된 레퍼런스

    • 객체 내 부모 클래스의 멤버만 접근 가능
    • p 는 자식 클래스 멤버 접근 불가
  • 업캐스팅 사레

    class Person {
       String name;
       String id;
       public Person(String name) {
       	  this.name = name;
       }
    }
    class Student extends Person {
       String grade;
       String department;
       
       public Student(String name) {
       	  super(name);
       }
    }
    public class UpcastingEx {
    	public static void main(String[] args) {
       	Person p;
           Student s = new Student("Lee Hi");
           // id 는 자동으로 null 로 초기화(객체에서만)
           
           p = s; //업캐스팅 발생 (사람 s 를 생물 p 로 변환)
           //같은 데이터 타입이 아니여서 p 가 s 의 해시코드를 관리할수없어야 하는데
           //업캐스팅을 하므로써 상위 영역의 데이터 정보(s 객체의 메모리 중 부모 필드 메소드)만 관리할 수 있도록
          
           System.out.println(p.name); //오류 없음
           
           //레퍼런스 s 를 이용하면 6개의 멤버에 모두 접근이 가능하지만
           //레퍼런스 p 를 이용하여서는 Student 객체의 멤버중 오직 Person의 멤버만 접근 가능하다.
           p.grade = "A"; //컴파일 오류 
           p.department = "Com"; //컴파일 오류
       }
    }
    //result
    //Lee Hi

업캐스팅

  • 참조 변수는 같은 객체 타입의 참조값(해쉬코드)만 할당 받아야함
  • 그런데, 상속 관계에서는
    • '부모 클래스의 참조 변수'(s) 가 '자식 인스턴의 참조값'(p) 을 할당 가능
    • 부모 클래스와 관련된 메모리가 상단(up)에 존재. 해당 영역만 사용

다운캐스팅

  • 부모 클래스 레퍼런스를 자식 클래스 레퍼런스에 대입

  • 업캐스팅된 것을 다시 원래대로 돌리는 것

  • 명시적으로 타입 지정

  • 상위영역만 사용하도록 업캐스팅이 발생한 것을

  • p 는 업캐스팅으로 상위영역만 사용가능하다

  • 전체를 관리할 수 있는 참조변수 s 를 선언하여 p 를 전달하는데, p 는 상위 영역만 제공하기 때문에 (student)p 로 다운캐스팅해주므로써 s 가 상위하위 영역 모두 사용할수있게 된다.

⏹ instanceof 연산자와 객체의 타입 판단

  • 업캐스팅된 레퍼런스로 객체의 진짜 타입을 구분하기 어려움
    • 부모 클래스는 여러 자식 클래스에 상속되기 때문
      • 부모 클래스 레퍼런스로 자식 클래스 객체를 가리킬 수 있다.
      • 예) '생물' 팻말(레퍼런스)이 가리키는 박스에 들어있는 개체의 타입이 사람인지, 동물인지 팻말만 보고서는 알 수 없음
  • instanceof 연산자
    • instanceof 연산자
      • 레퍼런스가 가리키는 객체의 타입 식별을 위해 사용
    • 사용법
      • 객체레퍼런스 instanceof 클래스타입
        • 연산의 결과 : true/false 의 불린 값

⏹ 업캐스팅 레퍼런스가 가리키는 객체는?

  1. 상속 관계에 있는 옆의 클래스 사례에서

  2. 다음과 같은 업캐스팅이 가능하므로

    Person p = new Person();
     Person p = new Student();    //업캐스팅
     Person p = new Researcher(); //업캐스팅
     Person p = new Professor();  //업캐스팅
  3. print(p); 를 호출하면, print() 메소드에서 person 이 어떤 객체를 가리키는지 알 수 없음

  • void print(Person) {
      //person 이 가리키는 객체가 Person 타입일 수도 있고
      //Student, Researcher, 혹은 Professor 타입일 수도 있다.
    }

⏹ Person 타입의 레퍼런스 person 이 어떤 타입의 객체를 가리키는지 알 수 없다.

Person jee = new Student();		//업캐스팅
Person kim = new Professor();	//업캐스팅
Person lee = new Researcher();	//업캐스팅

if(jee instanceof Person)		//jee 는 Person 타입이므로 true  	
if(jee instanceof Student) 		//jee 는 Student 타입이므로 true  	
if(kim instanceof Student)		//kim 은 Person 타입이 아니므로 false  
if(kim instanceof Professor)	//kim 은 Person 타입이므로 true  	
if(kim instanceof Researcher)	//Professor 객체는 Researcher 타입이기도 하므로 true
if(lee instanceof Professor)	//lee 는 Professor 타입이 아니므로 false  

if(3 instanceof int) 			//문법 오류. instanceof 는 객체에 대한 레퍼런스만 사용
  								//정수는 기본 데이터 타입. 클래스 타입 아님

if("java" instanceof String)    //true

: instanceof 해석 : Jee 라고 참조변수가 클래스 데이터 타입 Person 과 관련이 있는지를 물어보는것

⏹ instanceof 연산자 활용

  • instanceof 연산자를 이용하여 상속 관게에 따라 레퍼런스가 가리키는 객체의 타입을 알아본다.

  • 실행결과는?

    • instanceof 로 참조변수 p 가 해당 클래스데이터 타입과 관련이 있는지
    • 있으면 true 없으면 false
class Person {}
class Student extends Person {}
class Researcher extends Person {}
class Professor extends Researcher {}

public class InstanceOfEx {
	static void print(Person p){  //인자를 받아 참조변수 p 로 관리
    	if (p instanceof Person)
        	System.out.print("Person");
        if (p instanceof Student)
        	System.out.print("Student");
        if (p instanceof Researcher)
        	System.out.print("Researcher");
        if (p instanceof Professor)
        	System.out.print("Professor");
        System.out.println();
    }
    
    public static void main(String[] args) {
    	System.out.print("new Student() ->\t");
        print(new Student());  	//참조변수 p 가 Student 를 관리
        System.out.print("new Researcher() ->\t");
        print(new Researcher());	//참조변수 p 가 Researcher 를 관리
        System.out.print("new Professor() ->\t");
        print(new Professor());		//참조변수 p 가 Professor 를 관리
    }
}
//result
//new Student() -> 		Person Student
//new Researcher() -> 	Person Researcher
//new Professor() ->    Person Researcher Professor

//new Professor() 객체는 Person 타입이기도 하고, Researcher. Professor 타입이기도 하다.

⏹ 메소드 오버라이딩

  • 메소드 오버라이딩
    • 부모 클래스의 메소드를 자식 클래스에서 재정의 하는것

      • 부모 클래스의 메소드 이름, 메소드 인자 타입 및 개수, 리턴 타입 등 모든 것 동일하게 정의 \to 이 중 하나라도 다르면 메소드 오버라이딩 실패 -> 오버로딩이 됨
    • "메소드 무시하기", 덮어쓰기 로 변역되기도 함 \to 재정의!

    • 동적 바인딩 발생 조건 : [1] upcasting [2] 오버라이딩 메소드 (거의 upcasting 상황에서 발생한다.)

      • '오버라이딩 메소드' 가 무조건 실행되도록 '동적 바인딩' 됨
      • 정적/동적 : 컴파일 기준으로 구분(실행하는 시점에서 연결이 되는 점에서 동적 바인딩)

⏹ 메소드 오버라이딩 사례

  • Shape 클래스의 draw() 메소드를 Line, Rect, Circle 클래스에서 각각 오버라이딩 한 사례
  • draw() 메소드 \to 오버라이딩 됨
    • 부모 클래스에 void draw() 존재
    • 자식 클래스에도 인자도 없고, 리턴 타입도 void 동일한 draw() 가 존재 \to 자식 클래스가 'overriding' 함

⏹ 오버라이딩에 의해 자식 클래스의 메소드 호출

⏹ 오버라이딩 목적, 다형성 실현

  • 오버라이딩
    • 부모 클래스에 선언된 메소드를, 각 자식 클래스들이 자신만의 내용으로 새로 구현하는 기능
    • 상속을 통해 '하나의 인스턴스(같은 이름)에 서로 다른 내용 구현' 이라는 객체 지향의 다형성 실현
      • Line 클래스에서 draw()는 선을 그리고
      • Circle 클래스에서 draw()는 원을 그리고
      • Rect 클래스에서 draw()는 사각형을 그리고
  • 오버라이딩은 실행 시간에 다형성 실현
    • 동적 바인딩을 통해 실행 중에 다형성 실현
      • 실행 시, (오버라이딩으로 인해) 실제 수행되는 메소드 확인
      • 부모 클래스의 draw() 가 호출되었지만, 실제는 상속 받은 클래스에서 오버라이딩한 draw() 수행됨
        • 오버로딩은 컴파일 타임 다형성 실현

⏹ 메소드 오버라이딩 만들기

class Shape { //부모 클래스
	public Shape next;  //shape 을 관리할 수 있는 참조변수 next
    public Shape() {next = null;} //생성자
    public void draw() { //메소드
    	System.out.println("Shape");
    }
}

class Line extends Shape {
	public void draw() { //부모의 draw() 를 재정의 하는 메소드 오버라이딩
    	System.out.println("Shape");
    }
}

class Rect extends Shape {
	public void draw() { //draw() 를 재정의 하는 메소드 오버라이딩
    	System.out.println("Rect");
    }
}

class Circle extends Shape {
	public void draw() { //draw() 를 재정의 하는 메소드 오버라이딩
    	System.out.println("Circle");
    }
}

public class MethodOverridingEx {
	static void patin(Shape p) {
    	//p가 가리키는 객체 내에 오버라이딩된 draw() 호츌
        p.draw();
    }
    public static void main(String[] args) {
    	Line line = new Line();
        paint(line);			//Shape p = line; 업캐스팅
 		paint(new Shape());		//Shape p = new Shape();
        paint(new Line());		//Shape p = new Line(); 업캐스팅
        paint(new Rect());		//Shape p = new Rect(); 업캐스팅
        paint(new Circle());	//Shape p = new Circle(); 업캐스팅
    }
}

//result
//Line		//업캐스팅 후, 오버로딩 Line::draw()		
//Shape		//부모 클래스의 포인터가 같은 데이터 타입을 관리, draw()
//Line		//업캐스팅 후, 오버로딩 Line::draw()
//Rect		//업캐스팅 후, 오버로딩 Rect::draw()
//Circle	//업캐스팅 후, 오버로딩 Circle::draw()

⏹ 오버라이딩 활용

public class UsingOverride {
	public static void main(String[] args) {
    	Shape start, last, obj 
        
        //링크드 리스트로 도형 생성하여 연결
        start = new Line(); //start 는 Line 생성, 기본 데이터 타입 호출 -> 부모의 기본 생성자를 호출하는 super() 자동 생성 -> next = null 로
        // 업캐스팅이 발생되었고 부모 영역만 접근이 가능하다.
        
        last = start; //처음과 마지막을 가리키는 start 와 last 참조복사
        
        obj = new Rect(); //Rect() 호출 -> 자동 생성된 suepr() 에 의해 부모 생성자를 호출하여 next = null 로 초기화 하여 obj 라는 참조로 관리
        last.next = obj;  //obj 라는 참조값을 last 로 관리하는 next 에게 제공하여 업캐스팅
        //따라서 두개의 인스턴스가 연결이 (start 와 obj)되었다
        last = obj;
        obj = new Circle(); //업캐스팅 발생
        last.next = obj; //두번쨰와 세번째 연결 obj 로 관리하는 참조값을 last 가 관리하는 next 에 제공하여 연결
        last = obj; //last 에게 실제 마지막 위치를 가리키는 obj 참조값을 제공 
        
        //모든 도형 출력(메소드 호출)
        Shape p = start;  // 기존의 참조를 활용할 수 있지만 개별적으로 접근하기 위해 새로운 참조 p 를 하나 생성, 여기서도 업캐스팅 발생
        while(p != null) {  //계속 null 아닐동안 while 문 내부 실행
        	p.draw();  // 재정의된 draw() 메소드 호출, 실행할때 연계가 되는 동적 바인딩 발생
            p = p.next;  //다음으로 넘어가기 위해 p로 관리하는 next 참조값을 기존값을 삭제 시키고 새로 업데이드, 다음 메모리 영역에 접근이 가능함.
            
            //그 다음 다시 조건식으로 돌아가 while 문 작성.
        }
    }
}
//result
//Line
//Rect
//Line
//Circle

서로 다른 데이터 타입을 링크드 리스트로 연결할떄, 서로 다른 데이터 타입이 10개라면 10개의 종류에 해당하는 참조변수가 있어야함
하지만 이를 해결하기 위해 업캐스팅을 이용해서 상위 상속받는 부모로 연결할 수 있다.
이후 오버라이딩

⏹ 동적 바인딩

  • 실제 수행될 메소드는 실행 시 (run time) 에 결정
  • '동적' 은 컴파일 이후에 어떤 개념이 변화하거나 설정되는 것을 의미
  • '바인딩' 은 '연결된다' 라는 의미.
  • 즉. 실행 시에 수행될 메소드가 연결
  • 오버라이딩을 지원하면, 오버라이딩 메소드가 항상 호출
    • shape 을 상속을 받는 Circle 에서 shape 타입 참조변수 b 가 Circle 메모리 영역을 관리하도록 업캐스팅 후, b로 접근할 수 있는 영역은본인영역 paint 를 호출하고 그 안에 draw() 를 호출하려고 봤더니컴파일 시점에서는 Shape 클래스 내부의 draw() 가 실행되는 줄 알았더니 동적 바인딩으로 Circle 내부 draw() 가 실행되어 출력 Circle (참조변수는 자식 클래스가 우선순위?)

⏹ 오버라이딩과 super 키워드

  • super 는 부모 클래스의 멤버를 접근할 때 사용되는 레퍼런스
  • 자식 클래스에서만 사용
  • 부모 클래스의 메소드 호출
  • 컴파일러는 super 의 접근을 정작 바인딩으로 처리
class ShapeEx {
	protected String name;
	public void paint() {
		draw();
	}
	public void draw() {
		System.out.println(name);
	}
}

public class CircleEx extends ShapeEx {
	protected String name; //부모의 name 과 다른것
	@Override
	public void draw() {
		name = "Circle";
		//super.name = "Shape"; 그렇다면 부모 영역에 소속되어있는 name 을 접근하여 그정보를 shape 으로 업데이트 시키고 
		//super.draw(); super 에 있는 draw() 를 지정해서 사용하겠다하면 이 코드가 오버라이딩의 코드라고 하더라도 오버라이딩은 되었으나 그것을 무시하게 됨.
		System.out.println(name);
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ShapeEx b = new CircleEx();  //b 는 상위영역만 접근할 수 있다
		b.paint();  //상위영역의 paint 가 호출되어 그다음 paint 내부 draw() 가 호출됨 (우선순위 자식)
        //
	}

}
//result
그냥 : Circle

super 키워 추가 
Shape
Circle

둘 비교 꼭.

예를 들어서 상위 하위 영역을 관리하는 참조변수 p 가 있다면 p.name 을 호출한다면 우선순위에 의해 자식 클래스의 필드, 메소드가 먼저 출력됨

⏹ 메소드 오버라이딩 예제

  • 게임에서 무기를 표현하는 Weapon 클래스를 만들고 살상능력을 리턴하는 fire() 메소드를 작성하면 다음과 같다.
  • fire() 는 1을 리턴한다.
class Weapon {
	protected int fire() {
    	return 1;  //무기는 기본적으로 한 명만 살상
    }
}
  • 대포를 구현하기 위해 Weapon을 상속 받는 Cannon 클래스를 작성하라. Cannon 의 살상 능력이 10 이다.
  • fire() 메소드를 이에 맞게 오버라이딩하라. main() 을 작성하여 오버라이딩 테스트
class Cannon extends Weapon {
	@override
    protected int fire() { //오버라이딩
    	return 10;
    }
}

public class Overriding {
	public static void main(String[] args) {
    	Weapon weapon;
        weapon = new Weapon();
        System.out.println("The basic-weapon striking power:" + weapon.fire());
        weapon = new Cannon();  //업캐스팅
        System.out.println("The cannon's striking power:" + weapon.fire()); 
        //오버라이딩 된 fire() 호출됨
    }
}

//result
//The basic-weapon striking power: 1
//The cannon's striking power: 10
profile
공부한 것 기록용

0개의 댓글