P/G적 의미 : 하나의 참조변수로 여러 타입의 개체를 참조할 수 있는 것

    즉, 조상의 참조변수로 자손타입의 객체를 다룰 수 있는 것이다.


    Phone,java

    package kr.or.kihd.modifier1;
    
    public class Phone {
    	
    	//필드(멤버변수), 외부에서부터 접근 못하게 막는다.
    	protected String model;
    	private String color;
    	private String company;
    	
    	public Phone() {
    		
    	}
    	
    	//매개변수가 있는 생성자
    	public Phone(String model, String color, String company) {
    		super();
    		this.model = model;
    		this.color = color;
    		this.company = company;
    	}
    	
    	//getter() 제공
    	public String getModel() {
    		return model;
    	}
    
    	public String getColor() {
    		return color;
    	}
    
    	public String getCompany() {
    		return company;
    	}
    	
    	@Override
    	public String toString() {
    		String str = "모델 : "+this.getModel()+
    					 ", 색상 : "+this.getColor()+
    					 ", 제조회사 : "+this.getCompany();
    		return str;
    	}
    	
    }
    

     

    modifier1

    AccessClass.java

    package kr.or.kihd.modifier1;
    
    public class AccessClass {
    	
    	public static void main(String[] args) {
    		Phone phone = new Phone("iPhone12", "PBlue", "Apple");
    		phone.model ="LG";
    		
    				
    				
    	}
    }
    

     

    modifier2

    AccessClass.java

    package kr.or.kihd.modifier2;
    
    import kr.or.kihd.modifier1.Phone;
    
    public class AccessClass {
    	
    	public static void main(String[] args) {
    		Phone phone = new Phone("iPhone12", "PBlue", "Apple");
    		//phone.model ="LG";
    		
    				
    				
    	}
    }
    

    다형성의 참조

    조상타입의 참조변수로 자손타입의 객체를 참조할 수 있지만, 반대는 허용이 안된다.

    단, 메서드의 경우는 자손클래스에서 오버라이딩을 한 경우 자손클래스의 메서드가 호출된다.

     

    => 부모타입으로 생성된 인스턴스 객체도 오버라이딩에 의해서 메서드가 호출된다.

     

    축구선수 예제

    package kr.or.kihd.modifier3;
    
    //조상클래스
    public class Player {
    	
    	private String name;
    	private int age;
    	private int backNumber;
    	private int speed;
    	
    	//생성자
    	public Player(String name, int age, int backNumber, int speed) {
    		this.name = name;
    		this.age = age;
    		this.backNumber = backNumber;
    		this.speed = speed;
    	}
    
    	//getter메서드 제공
    	public String getName() {
    		return name;
    	}
    
    	public int getAge() {
    		return age;
    	}
    
    	public int getBackNumber() {
    		return backNumber;
    	}
    
    	public int getSpeed() {
    		return speed;
    	}
    	
    	public void info() {
    		System.out.println("이름 : " + this.getName());
    		System.out.println("나이 : " + this.getAge());
    		System.out.println("등 번호 : " + this.getBackNumber());
    		System.out.println("속도 : " + this.getSpeed());
    	}
    	
    		
    }
    

     

    package kr.or.kihd.modifier3;
    
    public class Striker extends Player{
    	
    	private int shoot;
    	
    	public Striker(String name, int age, int backNumber, int speed, int shoot) {
    		super(name, age, backNumber, speed);
    		this.shoot = shoot;
    	}
    	
    	public int getShoot() {
    		return this.shoot;
    	}
    	
    	@Override
    	public void info() {
    		super.info();		//player의 info를 호출
    		System.out.println("유효 슈팅 : " + this.getShoot());
    	}
    	
    }
    
    package kr.or.kihd.modifier3;
    
    public class MideFielder extends Player{
    	
    	private int pass;
    	
    	public MideFielder(String name, int age, int backNumber, int speed, int pass) {
    		super(name, age, backNumber, speed);
    		this.pass = pass;
    	}
    	
    	public int getPass() {
    		return this.pass;
    	}
    	
    	@Override
    	public void info() {
    		super.info();		//player의 info를 호출
    		System.out.println("패스 횟수 : " + this.getPass());
    	}
    	
    }
    
    package kr.or.kihd.modifier3;
    
    public class Defender extends Player{
    	
    	private int defence;
    	
    	public Defender(String name, int age, int backNumber, int speed, int defence) {
    		super(name, age, backNumber, speed);
    		this.defence = defence;
    	}
    	
    	public int getDefence() {
    		return this.defence;
    	}
    	
    	@Override
    	public void info() {
    		super.info();		//player의 info를 호출
    		System.out.println("방어 횟수 : " + this.getDefence());
    	}
    	
    }
    

     

    Test

    package kr.or.kihd.modifier3;
    
    public class PlayerTest {
    
    	public static void main(String[] args) {
    		
    		//다형성 미적용 코드
    		Player player = new Player("호우", 28, 11, 96);
    		player.info();
    		System.out.println();
    		
    		//다형성이 적용된 코드 (필드의 다형성)
    		//하지만, 원타입은 벗어나지 못함, 그래서 Striker클래스에 있는
    		//getShoot()메서드는 player2참조변수에서 접근이 안됨.
    		Player player2 = new Striker("손홍민", 28, 7, 96, 50);
    		
    		//메서드에서 상속관계에 있다면, 자손클래스에서 오버라이딩을 하게 되면
    		//현재 참조하고 있는 인스턴스의 메서드를 호출함.
    		player2.info();
    		System.out.println();
    		
    		Player player3 = new MideFielder("케빈 더브라위너", 29, 17, 98, 120);
    		player3.info();
    		System.out.println();
    		
    		Player player4 = new Defender("라모스", 28, 14, 29, 60);
    		player4.info();
    	}
    
    }
    

    다형성으로 인한 형변환

    형변환의 전제조건 - 상속, 구현관계에 있는 것만 객체타입 변환이 가능(매우중요)

    자손타입에서 조상타입으로 형변환은 생략 가능하지만, 반대는 명시적 형변환을 반드시 해야한다.

     

    instance of 연산자

    참조변수가 참조하는 인스턴스의 실제 타입을 체크하는데 사용한다.

    이항연산자, 연산결과는 boolean 값이 된다.

    instance of 연산결과가 true이면 ,해당 타입으로 형변환이 가능하다.

     

    참조변수와 인스턴스 변수의 연결 -> 오버라이딩 풀어서 설명

    멤버변수가 중복 정의된 경우는 참조변수의 원래 타입에 따라 연결되는 멤버변수가

    달라진다. (참조변수 형 타입에 영향을 받음)

    메서드가 중복정의 된 경우는 참조변수의 타입에 관계없이 항상 실제 인스턴스의 타입에 

    정의된 메서드가 호출된다. (참조하고 있는 인스턴스에 영향을 받음)

     


    업케스팅 예제

    package kr.or.kihd.polymorphism;
    
    public class Car {
    	
    	String color;
    	int door;
    	
    	public void drive() {
    		System.out.println("차가 달립니다.");
    		
    	}
    	
    	public void stop() {
    		System.out.println("차가 멈춥니다.");
    	}
    	
    }
    
    package kr.or.kihd.polymorphism;
    
    //자손클래스
    public class SportCar extends Car{
    	
    	public void SpeedUp() {
    		System.out.println("속도를 올립니다.");
    	}
    	
    }
    
    package kr.or.kihd.polymorphism;
    
    public class PoliceCar extends Car{
    	
    	public void siren() {
    		System.out.println("사이렌을 울립니다.");
    	}
    	
    }
    
    package kr.or.kihd.polymorphism;
    
    public class CarTest {
    	
    	public static void main(String[] args) {
    		
    		Car car = null;
    		SportCar sportCar = new SportCar();
    		SportCar sportCar2 = null;
    		PoliceCar policeCar = new PoliceCar();
    		
    		sportCar.SpeedUp();
    		
    		//업케스팅
    		car = sportCar; 			//1.업케스팅(자손->조상) : 조작할수 있는 멤버가 줄어듬.
    //		car.speedUp();              // X
    		
    		sportCar2 = (SportCar)car;  //2.다운케스팅(조상->자손) : 조작할수 있는 멤버가 늘어남.
    									//다운케스팅 할때, 반드시 명시적으로 형변환 코드를 작성해야 함.
    		sportCar2.SpeedUp();
    		
    		//3. 서로 관련없는 클래스들 간의 형변환 : 서로 상속관계가 아니기 때문에 형변환이 이루어질수 없음.
    //		sportCar = policeCar;       // X 
    		
    		
    	}
    	
    }
    

    instanceof 예제

     

    package kr.or.kihd.polymorphism;
    
    public class InstanceOf {
    	public static void main(String[] args) {
    		//Ctrl + t : 상속계층도를 볼수 있는 단축키
    				
    		SportCar sportCar = new SportCar();
    				
    				if(sportCar instanceof SportCar) {
    					System.out.println("SportCar로 타입변환이 가능합니다.");
    				}
    				
    				if(sportCar instanceof Car) {
    					System.out.println("Car로 타입변환이 가능합니다.");
    				}
    				
    				if(sportCar instanceof Object) {
    					System.out.println("Object로 타입변환이 가능합니다.");
    				}
    				//instancOf 연산자가 결과 true라는 것은
    				//실제 형변환이 가능하다라는 의미이며,
    				//아울러 상속관계에 있는 것이다.
    				
    	}
    		
    		
    }
    

     

    instanceof 예제2

    package kr.or.kihd.polymorphism2;
    
    public class Parent {
    	//타입체크를 한다.
    	int x = 100;
    	
    	public void type(Object obj) {
    		if(obj instanceof Parent) {
    			Parent parent = (Parent)obj; //강제 타입 케스팅(다운케스팅)
    			System.out.println("조상클래스의 멤버 x값 : " + parent.x);
    		}
    		else {
    			System.out.println("Parent타입의 객체가 아님, 상속관계에 있지 않은 클래스이다.");
    			//Parent와 상속관계에 있을때 객체를 만들겠다는 것
    		}
    	}
    	public void method() {
    		System.out.println("조상메서드 호출");
    	}
    	
    	
    }
    
    package kr.or.kihd.polymorphism2;
    
    public class Child extends Parent {
    	
    	int x = 200;
    	
    	@Override
    	public void method() {
    		System.out.println("자손메서드 호출");
    
    	}
    }
    
    package kr.or.kihd.polymorphism2;
    
    public class ReferTest {
    	
    	public static void main(String[] args) {
    		//다형성을 적용한 객체
    		Parent parent = new Child();
    		Child child = new Child();
    		
    		//"멤버변수"는 원래 타입을 벗어나지 못함.
    		System.out.println(parent.x);
    		System.out.println(child.x);
    		
    		//"멤버메서드"는 현재 참조하고 있는 인스턴스에 영향을 받음(오버라이딩)
    		parent.method();
    		child.method();
    		
    		parent.type(new Child());
    		parent.type(new Parent());
    		parent.type(new Car());
    	}
    	
    }
    

     

    • 네이버 블러그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기
    loading