Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

나의 IT일지

다형성 본문

프로그래밍 언어/Java

다형성

세레프 2023. 4. 18. 09:36

   변수에 선언한 타입과 다른 타입의 데이터 값을 저장할 때, 변수의 타입에 맞게 값을 변환해서 저장을 하였다. 이를 타입변환이라고 하는데, 타입변환데이터 타입을 변수의 타입에 맞게 바꿔서 저장하는 것으로, 프로그램 실행 도중에 자동으로 변환하는 자동변환타입변환할 타입을 선언해서 변환하는 강제변환 타입이 있다.

 

 이렇게 프로그램의 요소들이 상황에 따라 여러가지 형태를 가지게 되는 특성다형성이라고 하며, 오버로딩, 오버라이딩, 타입변환이 다형성에 속한다. 

 

 타입변환은 변수 뿐만아니라 객체에서도 가능한데, 클래스 타입 변환은 상속관계에 있는 클래스 사이에서만 발생된다. 

 

업캐스팅

 업캐스팅이란 부모클래스의 참조변수가 자식 클래스의 객체의 주소를 받을 때, 객체의 클래스타입이 부모 클래스타입으로 형변환 되는 것으로, 자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급할 수 있는 것이다.

  1. 부모클래스 참조변수 = new 자식클래스생성자
  2. 부모클래스 참조변수 = 자식참조변수

 위의 구조는 업캐스팅을 할 수 있는 구조로, 자식 객체의 주소가 부모클래스의 참조변수에 저장될 때, 자식 객체나 자식 참조변수는 자동적으로 타입이 변환된다. 1번째 형식은 부모클래스의 참조변수가 새로운 자식 객체를 지정한다면, 2번째 형식은 부모클래스의 참조변수가 기존의 자식 객체를 지정한다.

 즉, 부모클래스의 참조변수에 자식 클래스인 객체의 주소가 저장될 때, 해당 참조변수에는 객체의 타입이 부모클래스로 변환된 상태로 저장이 된다.

package pack0418;
class Human{
	String name;
	int age;
	String hobby;
	
	public Human(String name, int age, String hobby) {
		this.name = name;
		this.age = age;
		this.hobby = hobby;
	}
	
	void info() {
		System.out.println("name:"+name);
		System.out.println("age:"+ age);
		System.out.println("hobby:"+ hobby);
	}
}

class Student extends Human{
	int grade;
	public Student(String name, int age, String hobby,int grade) {
		super(name,age,hobby);
		this.grade=grade;
	}
	
	void info() {
		super.info();
		System.out.println("grade:"+grade);
	}
	void study() {
		System.out.println("공부하기");
	}
}
package pack0418;

public class Code2 {

	public static void main(String[] args) {
		Student st1 = new Student("김길동",25,"코딩",85);
		st1.info();
		
		Human H1 = new Student("김준식",35,"코딩",55);
		H1.info();
        
		Human H2 = st1;
		H2.info();
		
	}	
}

 이때, 참조변수는 자식 객체를 참조하지만 참조변수를 통해 접근 가능한 멤버는 부모 클래스의 멤버로 한정되어 있다. 그래서 "st1"는 자식클래스타입으로 자식 객체의 주소를 저장했기 때문에, 자식클래스의 멤버를 호출할 수 있으며, "H1"과 "H2"는 부모클래스타입으로 자식 객체의 주소를 저장했기 때문에, 부모클래스의 멤버만 호출할 수 있는 것이다. 이때, 자식클래스에서 부모 클래스의 멤버를 재정의 했을 경우, 참조변수는 재정의된 멤버를 호출한다.

 

 즉, 객체가 부모클래스로  자동 타입 변환하고 참조변수에 저장되면, 해당 참조변수는 부모 클래스에 선언된 변수와 메소드만 접근 할 수 있으며, 자식 클래스에서 멤버가 재정의했을 경우에 참조변수는 자식 클래스에 재정의된 멤버에 접근하는 것이다.

 

 이 업캐스팅은 매개변수를 객체로 받거야 하는경우나 참조변수의 객체 생성을 부모클래스로 선언하고 자식클래스의 객체 주소를 해당 참조변수에 저장하는 경우에 사용 된다. 

package pack0418;
class Animal{
	void breath() {System.out.println("숨쉬기");}
    public String toString(){
		return "동물";
	}
}
    
class Lion extends Animal{
	 public String toString(){
		return "사자";
	}
}
  
class Rabbit extends Animal{
	public String toString(){
		return "토끼";
	}
}
   
class Monkey extends Animal{
	public String toString(){
		return "원숭이";
	}
}
   
class ZooKeeper{
	void feed(Animal animal) {
		System.out.println(animal.toString()+"먹이주기");
	}
}
package pack0418;

public class Code3 {

		
		public static void main(String[] args) {
			Animal Ani1= new Aminal();
			Ani1 = new Lion();		//업캐스팅
			Lion lion1 = new Lion();
			Rabbit rabbit1= new Rabbit();
			Monkey monkey1= new Monkey();
			
			ZooKeeper  james=new ZooKeeper();
			james.feed(Ani1);
			james.feed(lion1);		//업캐스팅
			james.feed(rabbit1);		//업캐스팅
			james.feed(monkey1);		//업캐스팅
			
		}
	}

 그렇다면 업캐스팅을 하는 이유가 무엇일까? 업캐스팅을 하는 이유는 해당 부모클래스의 참조변수에 다양한 자식클래스의 객체를 받기 위해서 사용한다.

 즉, 참조변수를 자식클래스 타입로 선언하게 되면, 해당 참조변수는 자식클래스의 객체의 주소만 저장할 수 있지만, 부모클래스 타입로 선언하게 되면, 부모클래스를 상속하고 있는 자식클래스의 객체의 주소를 전부 저장할 수 있게 된다.

 

다운캐스팅

 이렇게 업캐스팅을 통해 객체가 자동타입변환이 되어서 참조변수에 저장이 되면, 해당 참조변수는 부모에 선언된 필드와 메서드만 사용할 수 있다.

 하지만, 자식에 선언한 필드와 메서드를 사용해야 하는 경우가 있는데, 이런 경우에는 해당 객체를 강제적으로 자식 클래스로 변환을 시켜줘야 한다. 이를 다운캐스팅이라고 한다.

 

 다운캐스팅이란 부모타입을 자식타입으로 강제타입전환하는 것으로, 업캐스팅된 부모클래스의 객체만 자식클래스로 타입변환이 가능하다.

자식클래스 변수 = (자식클래스) 업캐스팅된 부모참조변수

package pack0418;

public class Code1 {
	public static void main(String[] args) {
		Student st1 = new Student("김길동",25,"코딩",85);
		st1.study();
		
		Human H1 = st1;
//		H1.study();				//Human클래스에 study()가 정의 되어 있지 않음
		
		Student st2 = (Student)H1;
		st2.study();
	}
}

 이처럼 업캐스팅한 "H1"변수의 경우에는 study()메서드를 사용할 수 없지만, 다운캐스팅한 "st2"변수는  study()메서드를 사용할 수 있다.

 


instanceof 연산자

 어떤 객체가 어떤 클래스의 인스턴스인지 확인하기 위한 연산자로, 주로 매개값의 클래스 타입을 조사할 때 사용되거나,  강제 타입 변환이 필요할 경우 반드시 매개변수에 들어오는 객체가 해당 매개변수의 클래스 타입의 인스턴스인지 확인할 때 사용된다.

객체 instanceof 클래스

instanceof 연산자는 좌측에는 객체가 오며, 우측에는 클래스 타입이 오는데, 좌측의 객체가 우측의 클래스의 인스턴스일 경우에는 true, 아닐 경우에는 false가 출력된다.

package pack0418;
class Animal{
	void breath() {System.out.println("숨쉬기");}
    public String toString(){
		return "동물";
	}
}
    
class Lion extends Animal{
	 public String toString(){
		return "사자";
	}
}
  
class Rabbit extends Animal{
	public String toString(){
		return "토끼";
	}
}
   
class Monkey extends Animal{
	public String toString(){
		return "원숭이";
	}
}
   
class ZooKeeper{
	void feed(Animal animal) {
		System.out.println(animal.toString()+"먹이주기");
	}
}
package pack0418;

public class Code3 {

		
		public static void main(String[] args) {
			Animal Ani1= new Aminal();
			Ani1 = new Lion();		//업캐스팅
			Lion lion1 = new Lion();
			Rabbit rabbit1= new Rabbit();
			Monkey monkey1= new Monkey();

		System.out.println(lion1 instanceof Animal);
		System.out.println(rabbit1 instanceof Animal);
		System.out.println(monkey1 instanceof Animal);
			
		}
	}

'프로그래밍 언어 > Java' 카테고리의 다른 글

인터페이스  (0) 2023.04.20
추상화  (0) 2023.04.19
상속  (0) 2023.04.15
생성자  (0) 2023.04.13
객체 배열  (0) 2023.04.11
Comments