▶ 다형성

기본적으로 자바의 다형성에 대해서 설명해보세요~!

> 오버로딩(Overloading)과 오버라이딩(Overriding)을 설명하면 됩니다.

오버로딩 (overloding) 같은 메서드 이름,다른 인자 목록에서 다수의 메서드를 중복 정의
오버라이딩 (overriding) 같은 메서드 이름 같은 인자 목록에서 부모 클래스의 메서드를 재정의

o 정의

- 하나의 타입에 여러가지 객체를 대입해 다양한 실행 결과를 얻는 것이다

 

o 다형성을 구현하는 기술

- 상속 또는 인터페이스의 자동 타입 변환

- 오버라이딩(Overriding)

 

o 사용하는 이유

- 코드 구조가 향상되어 가독성을 증가

- 유지보수 용이 (메소드의 매개변수로 사용)

 

o 다형성의 이용

첫 번째로 메소드의 매개변수를 선언할 때, 다형성을 많이 이용한다.

일반적으로 메소드 매개변수는 자식 클래스보다는 부모 클래스 타입으로 선언하는 것이 좋다 (하나의 메서드 선언으로 다양한 타입의 인자를 받아 처리하기 위해서이다)

현재 참조형 변수가 어떤 클래스 형의 객체 주소를 참조하고 있는지 확인 할 때 사용

클래스 타입이 맞으면 true, 맞지 않으면 false 반환

 

o 객체배열과 다형성

다형성을 이용하여 상속 관계에 있는 하나의 부모 클래스 타입의 배열 공간에 여러 종류의 자식 클래스 객체 생성 가능

 

Hobby[] poltArr = new Hobby[4];
poltArr[0] = new Collecting(3,100,"도자기");
poltArr[1] = new Collecting(6,400,"우표");
poltArr[2] = new ReadingBook(4,200,100);
poltArr[3] = new ReadingBook(5,300,200);

 

 

o 매개변수와 다형성

다형성을 이용하여 메소드 호출 시 부모타입의 변수 하나만 사용해 자식 타입의 객체를 받을 수 있음

 

public void execute( ) {

     driveCar (new Sonata( ));

     driveCar (new Avante( ));

     driveCar (new Grandure( ));

}

public void driveCar (Car c) { }

 


▶ 캐스팅 (Casting)

캐스팅이란 타입을 변환하는 것을 말하며 형변환이라고도 한다.

자바의 상속 관계에 있는 부모와 자식 클래스 간에는 서로 간의 형변환이 가능하다

 

 업캐스팅 (상향 형변환)

부모 클래스 객체가 있는 곳을 자식 클래스 객체로 대치하는 것

부모클래스 참조변수 = new 자식클래스 생성자( );

- Person p = new Student();

∘ 부모 클래스로 형변환이 되는것이다

∘ 컴파일러에 의해 자동으로 형변환된다

∘ 업캐스팅이 된 이후 부모 클래스의 참조변수는 부모 클래스로부터 상속받은 멤버만 호출 할 수 있다

∘ 단 업캐스팅이 되더라도 자식 클래스에서 재정의된 메서드는 참조할 수 있고, 부모 클래스로부터 상속받은 메서드는 은닉된다

 

 업캐스팅을 사용하는 이유 (오버라이딩의 목적)

서브클래스 객체 생성하면 슈퍼클래스, 서브클래스 둘 다 접근이 가능한데, 도대체 캐스팅을 왜 사용할까?

도대체 왜????????

=> 상속을 받은 서브클래스가 몇 개이든 하나의 인스턴스로 묶어서 관리할 수 있기때문이다

     즉 더 공통적으로 할 수 있는 부분을 간단하게 만들기위해서인것

아래 예시를 보자

더보기

부모 클래스 Employee의 상속 관계를 나타낸 것이다

   자식 클래스Saleman Manager Consultant

직원이 많아져서 인스턴스가 추가가 되면 전형적인 하드코딩이 되어버린다!

자 그럼 우리가 캐스팅을 사용하는 이유는 인스턴스를 1개(슈퍼클래스)로 잡아서 자식클래스를 담아놓고 관리하기 위해서다.

부모클래스가 관리할 수 있다 -> 다형성: 메서드를 각각 다른 형태로 사용 -> 자식클래스를 여러 가지 형태로 만들 수 있다.

*캐스팅을 사용하는 이유(오버 라이딩의 목적) : 하나의 인스턴스(슈퍼클래스)로 자식클래스를 전부 관리할 수 있다. *

 

 Object는 자바 클래스의 상속 구조에서 최상위 클래스이다. 결국 모든 자바 클래스는 Object의 자식 클래스가 된다

 

UpCasting Example

class Person{
	String name;
	Person(String name){
		this.name = name;
	}
}
/*------------------------------------------------------------*/
class Student extends Person{
	String check;
	Student(String name){
		super(name);
	}
}
/*------------------------------------------------------------*/
public class Main{
	public static void main(String[] args){
		Person p = new Student("홍길동");	// 업캐스팅 (UpCasting)
		p.name = "이름이다.";
		System.out.println(p.name);

		//p.check = "컴파일 에러 발생";
		// p는 Person 타입이기 때문에 자신의 클래스의 멤버(String name)에만 접근이 가능하다
	}
}

 

 

 

 

 다운캐스팅 (하양 형변환) (강제 타입 변환)

업캐스팅된 것을 다시 원상태로 돌리는 것

∘ 조건 : 자식 타입을 부모 타입으로 자동 변환 후, 다시 자식 타입으로 변환할 때

자식 클래스로의 다운캐스팅을 할때는 타입을 명시적으로 지정해줘야한다

자식 클래스 참조변수 = (자식클래스) 부모 클래스 타입;

∘ Student s = (Student)p;

- 자식 클래스 = 부모 클래스

- 자식 클래스로 형변환이 되는 것이다

- 컴파일러에 의해 자동으로 형변환되지 않는다

- 참조 가능한 영역이 확대된다

 

∘ 다운 캐스팅을 사용하는 이유

- 자식 타입이 부모 타입으로 자동 변환 => 부모 타입에 선언된 필드와 메소드만 사용 가능해게되니

=> 자식 타입에 선언된 필드와 메소드를 다시 사용해야 할 경우 다운 캐스팅이 필요하다

 

DownCasting Example

class Person{
	String name;
	Person(String name){
		this.name = name;
	}
}

class Student extends Person{
	String check;
	Student(String name){
		super(name);
	}
}

public class Main{
	public static void main(String[] args){
		Person p = new Student("홍길동");	// 업캐스팅 (UpCasting)
        
		Student s = (Student)p;	// 다운캐스팅
		s.name = "김유신";
		s.check = "check!";
	}
}

 

 

Total Example (UpCasting / DownCasting)

더보기

 업캐스팅

class Person { 
	public void Method_0() { 
		System.out.println("Person Method_0()"); 
	} 
	public void Method_1() { 
		System.out.println("Person Method_1()"); 
	} 
} 

class Girl  extends Person{	//소녀 
	public void Method_0() {
		 System.out.println("Girl Overriding Method_0()"); 
	} 
	 public void Method_2() { 
		 System.out.println("Girl mMethod()"); 
	} 
} 

class Boy extends Person {	//소년 
	public void Method_0() {	//오버라이딩 
		System.out.println("Boy Overriding Method_0()"); 
	} 
	public void Method_3() { 
		System.out.println("Boy Method_3()"); 
		}
	}

	public class Casting { 
		public static void main(String[] args) { 
		Person person; 
		Girl  girl = new Girl (); 
		person = girl;	//업캐스팅 (UpCasting) 
		
		person.Method_0();		//Girl의 오버라이딩된 메소드 호출 
		person.Method_1();		//Person의 메소드 호출 
		//person.Method_2();	//에러!!! 부모클래스 인스턴스는 자식클래스 메소드 사용불가능 
	}
}
// 실행결과
Girl Overriding Method_0()
Person Method_1()

 다운캐스팅

 

 

instanceof 이란?

 instanceof는 참조변수(String,Scanner 등)가 참조하는 객체의 타입(객체가 어떤 클래스인지, 어떤 클래스를 상속받았는지)을 검사하는 연산자로 if문과 함께 사용한다

- 반환값은 true 또는 false 이다

 

∘ instanceof 연산자를 쓰는 이유

다형성으로 인해 여러타입이 전달될 수 있으므오 각각의 인스턴스 타입에 따라 서로 다른 작업을 하기 위해서이다

 

1. 매개변수의 타입을 부모 타입으로 선언한다

2. instanceof 연산자를 사용해 타입을 검사한다

3. 타입 변경 후 각각 작업을 한다

 

∘ 표현식

if(c instanceof Sonata) {

          ((Sonata)c).moveSonata( );

} else if (c instanceof Avante) {

          ((Avante)c).moveAvante( );

} else if (c instanceof Grandure) {

          ((Grandure)c).moveGrandure( );

 

 예시

더보기
import java.util.Scanner;

/*-------------------------추상 클래스 Shape-------------------------*/
abstract class Shape {	//추상클래스 선언

	protected int x, y;	//필드 선언

	public abstract double getArea();	//추상 메서드 //double이 반환형
}
/*-------------------------자식 클래스 Circle-------------------------*/
class Circle extends Shape {	//Shape을 상속받은 자식 클래스 Circle
	private int radius;	//필드 선언

	public Circle() {	//생성자
	}

	public Circle(int radius) {	//생성자 오버로딩
		this.radius = radius;		
	}

	@Override	
	public  double getArea() {	//추상메서드getArea 재구현
		return radius * radius * 3.14;
	}
}
/*-------------------------자식 클래스 Rectangle-------------------------*/
class Rectangle extends Shape {	//Shape을 상속받은 자식 클래스 Rectangle
	private int width, height;	//필드 선언

	public Rectangle() {	//생성자 선언
	}

	public Rectangle(int width, int height) {	//생성자 오버로딩
		this.width = width;
		this.height = height;
	}

	@Override
	public double getArea() {	//추상메서드getArea 재구현
		return (double) (width * height);
	}
}
/*-------------------------실행 클래스-------------------------*/
public class ShapeMain {
	static Scanner scan = new Scanner(System.in);

	public static void main(String[] args) {
		Shape s = null; // 부모클래스의 참조변수 선언
		while (true) {
			System.out.print("\n***Shape Select***\n1. 원\n2. 사각형\n3. 종  료\n선택(1-3) : ");
			int no = scan.nextInt();
			switch (no) {
			case 1:
				s = new Circle(5); // 업캐스팅 (Circle로 대체)
				break;
			case 2:
				s = new Rectangle(4, 5); // 업캐스팅 (Rectangle로 대체)
				break;
			case 3:
				System.out.println("프로그램을 종료합니다.");
				System.exit(1);
			}
			if (s instanceof Circle) {	//Circle객체는 Shape클래스를 상속받은게 맞다
				System.out.printf("원의 넓이 : %.2f\n", s.getArea());
			} else {	//Rectangle객체는 Shape클래스를 상속받은게 맞다
				System.out.printf("사각형의 넓이 : %.0f\n", s.getArea());
			}
		}
	}
}

'Language > Java' 카테고리의 다른 글

예외 (Exception Event)  (0) 2022.02.22
내부 클래스 (중첩 클래스)  (0) 2022.02.21
인터페이스 (interface)  (0) 2022.02.21
추상 클래스/메소드  (0) 2022.02.21
클래스  (0) 2022.02.21