JAVA

[JAVA] 다형성 / 클래스가 매개변수 or 반환타입 인경우 + 다형성

sian han 2022. 3. 2. 20:00

 

※ 다형성

 - 여러가지 형태를 가질 수 있는 능력

 - 부모 타입의 참조변수로 자식의 인스턴스를 참조할 수 있도록 함으로써 다형성을 구현
 - 여러 개의 개별적인 클래스를 하나의 부모 클래스 객체로 통합 관리하여 그 효율성을 높인 것

 

 

 

▼다형성 대표형식

 - ★★★부모에 자식을 넣는다 ( = 부모에 자식 객체 대입 = 부모의 참조변수로 자식의 인스턴스 참조 )

Parent p = new Child;
p.method(); // => child 에서 오버라이딩 된 메서드 출력됨

 

 

 

 

▶ 다형성 특징

 - 위와같이 다형성을 이용해 부모에 자식을 넣으면 자식의 오버라이딩 메서드가 호출됨

     - 부모의 참조변수 (p) 로는 부모의 멤버들만 사용가능, 

                                        자식만의 메서드는 호출불가

 - 부모타입이 파생된 모든 자식 타입을 가리킬 수 있으므로 부모 타입의 변수로 모든 자식 타입을 일관되게 관리할 수 있다 

 

 

 

[ 부모의 참조변수로는 부모의 멤버만 접근 가능
    단 , 오버라이딩 메서드가 있다면 자식의 오버라이딩 메서드 호출 ]

△ 위 문법 실감나게 익혀보기

lass Parent{
	int x=100;
	
	public void method() {
		System.out.println("Parent");
	}
}
class Child extends Parent{
	int x=300;
	
	public void method() {
		System.out.println("Child~");
	}
}
Parent p = new Child(); // 다형성
		System.out.println("p.x="+p.x); // 부모의 참조변수로는 부모의 멤버만 접근가능. 
				 		//오버라이딩되었으면 300이 나왔겠지만 오버라이딩 안되었기때문에 위 기본조건을 따라 100이 나옴
		 p.method();			// => 300이 아님 !! 100이다 100 !!!

 

 

 

 

 

▶다형성을 이용하여 메서드 만들고 호출하기

 

1.  매개변수클래스 인 경우

▷만들기

public static void func1(Circle c){
		c.draw();
		c.delete();
		c.sayCircle();
	}

 

▷호출하기

 Q. 클래스를 어떻게 매개변수로 넣지 ? => new 로 객체생성해서 ! 

Circle c = new Circle();
func1(c);

↓간단히

func1(new Circle());

 

만약 func1 메서드가 다른 클래스(Work) 에 소속되어있는 메서드라면

Work 클래스 호출 후 참조변수. 해서 호출하면된다 ! 

Work a = new Work();
a.func1(new Circle());

▷만들기

class AAA{
	public void method1(Cat c) {
		c.bark();
	}

▷호출하기

AAA obj = new AAA();
		
		obj.method1(new Cat());

 

 

 

 

 

 

1-1. 매개변수 클래스 인 경우 - 매개변수의 다형성

 

▷만들기

	public static void func2(Shape sh) {
		sh.draw();
		sh.delete();
	}

매개변수가 부모클래스(shape) 인 상황.

    이럴땐 main()에서 >>>자식객체<<<를 넣어 호출한다 ! 

 

 

▷호출하기 (정석) 

Shape sh = new Triangle();
Circle c = new Circle();
		func2(c);

 => 1 ) 부모에 자식을 넣는다 ( 이때 자식은 아무 자식이나 넣어도 됨 )    

      2 ) 매개변수로 넣어줄 클래스 객체 생성을 한다

      3 ) 메서드안에 객체생성한 참조변수를 넣어준다

 

= > Shape draw , delete : 그린다, 지운다 => Circle 클래스 참조변수 c 넣어줌 => 원을 그린다, 원을 지운다

     : 그린다, 지운다 => 원을 그린다, 원을 지운다

      

↓간단히

func2(new Triangle());
func2(new Circle());

▷만들기

class AAA{
public void method2(Animal an) {
		an.bark();
	}

▷호출하기 

AAA obj = new AAA();
obj.method2(new Cow());

 

 

 

 

 

 

2.  반환타입이 클래스인 경우

  - return type 자리에 클래스명 써주면 됨 (★★★반환타입이 Circle(클래스)이면 Circle 객체가 리턴된다★★★) = ( 본인의 객체가 리턴되는 것 ) 

 

▷만들기

public static Circle func3() {
		Circle c = new Circle();
		return c;
	}

▷호출하기 

  - 1 ) 메서드명 부르기                func3

  - 2 ) class로 받기                     Circle c2 = func3();

  - 3 ) 참조변수. 으로 호출하기      c2.delete();

Circle c2 = func3();
c2.delete();

▷만들기

class AAA{
public Cat method3() { 
		return new Cat();
	}

▷호출하기 

AAA obj = new AAA();
Cat c=obj.method3();

 

 

 

 

 

 

 

 

2-1. 반환타입이 클래스인 경우 - 다형성이용

  - ★★★ 반환타입이 Shape(부모) 이면 자식객체가 리턴된다 ★★★

 

▷만들기 [1]

public static Shape func4 (int type) {
		Shape sh = null;
		if(type==1) {
			sh = new Circle();
		}else if (type==2) {
			sh = new Triangle();
		}
		return sh;
	}

 

메서드에서 바로 리턴하는 경우 [2]

// [1] 이랑 결과는 똑같음

  - 반드시 else 를 추가해줘야 함

public static Shape func4 (int type) {
		Shape sh = null;
		if(type==1) {
			return new Circle();
		}else if (type==2) {
			return new Triangle();
		}else {
			return sh; // 반드시 else를 추가해줘야 함.
		}
	}

 

▷호출하기

Shape sh2 = func4(3);
sh2.draw();

▷만들기

class AAA{
public Animal method4() {
		return new Cow(); 
	}

▷호출하기 

AAA obj = new AAA();
Animal an=obj.method4();

 

 

 

 

 

 

2-2. 반환타입이 클래스인 경우 - 다형성이용 또해보기

 

▷만들기

★★★ 반환타입이 Shape(부모) 이면 자식객체가 리턴된다 ★★★

public static Shape createShape(int type) {
		//다형성 이용
		Shape s2 = null; // 클래스 초기화
		if(type==1) {
			s2 = new Circle();
		}else if (type==2) {
			s2=new Triangle();
		} 
		return s2;

  = type 이 1 일경우 자식클래스 Circle리턴,

     type 이 2 일경우 자식클래스 Triangle 리턴.

 

 

▷ 호출하기

 ( 만든 (반환타입이 클래스인) 메서드 호출하기 ) 

Shape s1 = createShape (type);
		if(s1!=null) { //참조변수. 사용할때는 다음과 같이 if 문으로 null체크를 해주는것이 좋다
		s1.delete();
		s1.draw();
		}else {
			System.out.println("잘못입력 !");
			return;

참조변수. 메서드명 으로 사용하면 됨 ! 

 

 

 

 

 

 

 

다형성 이용하여 클래스 배열만들기

(일반) Triangle 배열 만들고, 요소 3개 넣고, draw ()메서드 호출

Triangle [] arr = new Triangle[3];
		arr[0] = new Triangle();
		arr[1] = new Triangle();
		arr[2] = new Triangle();
		
		for(int i=0;i<arr.length;i++) {
			arr[i].draw();
		}

 

(다형성) Triangle 의 부모 Shape 배열만들고 호출

pArr[0] = new Circle();
		pArr[1] = new Triangle();
		pArr[2] = new Circle();
		
		for(int i=0;i<pArr.length;i++) {
			pArr[i].draw();
			pArr[i].delete();
			
		}

 

 


※ 빠른찾기

 

(1) #다형성 #오버라이딩메서드호출 #UpCasting

Animal ani=null;
	switch (type){
		case 1: ani = new Cat();
			break;
		case 2: ani=new Dog();
			break;
		case 3: ani=new Cow();
			break;
		default:
			System.out.println("잘못 입력함!!!");
			return;
	}//switch
	
	ani.bark();

 

(2) #다형성 #DownCasting #자식만의 메서드 호출

if (ani instanceof Cat){
		Cat m=(Cat)ani;
		m.showCat();
	}else if (ani instanceof Dog)	{
		Dog t=(Dog)ani;
		t.showDog();
	}else if (ani instanceof Cow)	{
		Cow d=(Cow)ani;
		d.showCow();
	}

 

(3) #배열 #4개요소넣기 #오버라이딩메서드호출

Animal[] arr = new Animal[4];
	arr[0]=new Cat();
	arr[1]=new Dog();
	arr[2]=new Cow();
	arr[3]=new Dog();

	for (int i=0; i<arr.length; i++)	{
		arr[i].bark();
	}//for

 

(4) #배열 #DownCasting #모든배열요소의 자식만의 메서드 호출 

for (int i=0; i<arr.length; i++)	{

		if (arr[i] instanceof Cat){
			Cat m=(Cat)arr[i];
			m.showCat();
		}else if (arr[i] instanceof Dog)	{
			Dog t=(Dog)arr[i];
			t.showDog();
		}else if (arr[i] instanceof Cow)	{
			Cow d=(Cow)arr[i];
			d.showCow();
		}
	}//for

(4-1) 자식만의 메서드를 호출하는 부분을 메서드로 만들어서 처리

for (int i=0; i<arr.length; i++)	{
		callAnimal(arr[i]);

	}//for
    }

 

(5) #배열 #DownCasting #자식만의 메서드 호출 #Only is one #instanceof 가 Cat 인것만 나옴

if (ani instanceof Cat){
		Cat m=(Cat)ani;
		m.showCat();
	}else if (ani instanceof Dog)	{
		Dog t=(Dog)ani;
		t.showDog();
	}else if (ani instanceof Cow)	{
		Cow d=(Cow)ani;
		d.showCow();
	}