22.5.13 [HackerRank]Covariant Return Types

서태욱·2022년 5월 13일
0

Algorithm

목록 보기
1/45
post-thumbnail

✅ 문제 분석

메인 메소드에서 state의 이름(WestBengal, AndhraPradesh)을 통해서 사용자가 작성한 클래스와 메소드를 사용해 그 주의 꽃을 프린트하도록 만들어야 한다.

문제에 주어진 숨긴 코드는 서브 클래스인 state 이름을 나타내는 단일 문자열을 읽고, 서브 클래스와 연결된 메소드를 테스트한다. stdin으로 인풋할 것은 없다.

출력은 입력된 문자열의 클래스 이름에 해당하는 객체를 만들고, 해당 클래스를 만들고, 그 클래스에 해당하는 주의 꽃을 프린트 하는 메소드가 실행된다. 출력 역시 stdout을 통해 하지는 않는다.

(AndraPradesh 객체의 yourNationalFlower 메소드는, Lilly 클래스의 인스턴스를 반환하고, Lilly 클래스의 whatsyourName 메소드는 숨겨진 코드 검사기에 의해 리턴된다.)

🌱 배경지식

공변 반환 유형(Covariant Return Types)

OOP에서 메소드가 오버라이딩 될 때, 더 narrow한 타입으로 교체할 수 있다는 의미. narrow 하다는 것은 하위 서브 클래스라고 생각하면 될 듯 하다.
(공변성: 자신이 상속받은 부모 객체로 타입을 변화시킬 수 있다는 뜻)

클래스는 Sub에 오버라이딩 하면 가장 가까운 Super에서 상속한 다음 필요에 따라 동작을 수정할 수 있다. 오버라이딩한 메서드는 오버라이딩한 메서드 선언, 이름, 매개변수 유형과 개수, 리턴 타입이 모두 동일해야 한다.

그런데, 리턴 타입을 Super의 하위 타입(Sub)으로 반환할 수 있는데, 이를 공변 반환 유형이라고 한다.

class Super{
	Super of(int type){
		return new Super();
	}
}

class Sub extends Super{
	// covariant return type
	@Override // Super 클래스를 오버라이드 했으면
    Super of(int type){
		if(type == 1) return new Super();
		else return new Sub(); // 원래 메소드가 new Super() 형식의 객체를
        // 반환할 텐데, 서브 클래스는 어차피 수퍼 클래스가 할 수 있는 일을 할 수 있기 때문에 리턴 타입을 서브로 해주어도 문제가 생기지 않는다.
	}
}

메소드 오버라이딩

class Animal {
    String name;

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

class Dog extends Animal {
    void sleep() {
        System.out.println(this.name + " zzz");
    }
}

class HouseDog extends Dog {
    void sleep() {
        System.out.println(this.name + " zzz in house");
    }
}

public class Sample {
    public static void main(String[] args) {
        HouseDog houseDog = new HouseDog();
        houseDog.setName("happy");
        houseDog.sleep();  // happy zzz in house 출력
    }
}

Animal 클래스를 상속받은 Dog 클래스는 이름 zzz이 프린트 되는 sleep이라는 메소드를 구현하고 있다.
이때, 집에서 기르는 HouseDog이라는 클래스를 만들어 Dog 클래스를 상속시키고,
sleep 메소드를 재정의해준다. 집에서 기르는 개는 in the house에서 잔다고 프린트해주는 것이다.
이렇게 되면 HouseDog 클래스의 sleep 메소드를 호출할 경우에는 수퍼 클래스(Dog)의 메소드는 호출되지 않는다.

✏️ 해설

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

//Complete the classes below
class Flower {
    String whatsYourName() {
        return "I have many names and types.";
    }
}

class Jasmine extends Flower {
    @Override
    String whatsYourName() {
        return "Jasmine"; //원래 오버라이딩 하면 매개변수, 리턴 타입을 같게 해줘야 하지만, 공변 반환을 하면 Sub class 타입으로도 반환할 수 있다.
    }
}

class Lily extends Flower {
    @Override
    String whatsYourName() {
        return "Lily"; 
    }
}

class Region {
    Flower yourNationalFlower() {
        return new Flower();
    }
}

class WestBengal extends Region {
    @Override
    Flower yourNationalFlower() {
        return new Jasmine();
    }
}

class AndhraPradesh extends Region {
    @Override
    Flower yourNationalFlower() {
        return new Lily();
    }
}


public class Solution {
  public static void main(String[] args) throws IOException {
      BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
      String s = reader.readLine().trim();
      Region region = null;
      switch (s) {
        case "WestBengal":
          region = new WestBengal();
          break;
        case "AndhraPradesh":
          region = new AndhraPradesh();
          break;
      }
      Flower flower = region.yourNationalFlower();
      System.out.println(flower.whatsYourName());
    }
}

👉 참고

profile
re:START

0개의 댓글