본문 바로가기
코딩

2022.02.17_9일차_다형성과 추상클래스

by 흥뷰자 2022. 2. 23.

09일차 학습내용

1. 다형성 polymorphism
2. 추상클래스
3. 인터페이스 interface 



sc.close( ) <9:38 Test91 아쉬운 부분 더 정리 




1. 다형성 polymorphism  


여러가지 형태를 가질 수 있는 능력인데, 상속관계에서 성립 가능합니다.
참조형의 업/다운 캐스팅 

다형성 객체 생성 기본 객체 생성
class A {int x;}                   A 부모클래스
class B extends A {int y;}     B 자식클래스

-----------------------------------
메인메서드 내부
A a = new B();  -> x, y를 가지고는 있지만 
                     -> 사용시 a.멤버명에서 쓸 수 있는건 x뿐. 
                    (-> y를 쓰고싶으면 다시 형변환하면 가능)


▶ A부모타입 변수에 B자식타입 객체를 생성합니다. 가능합니다.  반대로는 안됩니다.
(형변환에서 큰 기본형에 작은 기본형을 넣는게 가능했던 것도 가능하고, 반대는 불가능하듯이 말입니다.)
작은 애한테 큰 옷을 입혀주는거라 업캐스팅입니다.




------------------------------------------
메인메서드 내부
A a = new A();   -> x    -> 사용할 땐 a.멤버명, x
B b = new B();   -> x, y -> 사용할 땐 b.멤버명, x,y둘다쓴다









A a;
B b = new B ();
a = b; 

▶ 자식 객체를 부모 변수에 담은것과 동일한 것입니다.
그런데, 여기서는 a=b; 만 봐서는 b의 타입을 잘 알 수 없기 때문에 b가 A타입의 객체라는 것을 형변환표기법으로 표시해주는 것이 좋습니다. 여기서는 생략해도 컴파일 에러는 없습니다.

a = (A) b; 


A a = new A();
B b;
b = a ;   => 컴파일 에러 발생
b = (B)a; => 컴파일 에러X but 런타임 에러 발생
                                         (ClassCastException)
▶ 부모 객체를 자식변수에 담을 수는 없습니다. 런타임에러를 방지하려면 형식만 갖추면 되는 것이 아니라 실제 들어있는 게 무엇인지 파악해야 합니다. 




타입이 안전하지 않다(자바의 타입 엄격성) -> 제네릭도입





A a;
B b = new B();
B b2;
a = b;  ▶컴파일 에러X 정상작동(형변환 생략 가능)
b2 = a;  ▶컴파일 에러 (실체가 B객체여도 형변환생략불가)
b2 = (B)a; ▶정상작동 (실체가 자식이라고 자식옷 입히는거 다운캐스팅) (b2는 이제 y를 쓸 수 있습니다.)
 

so, 이러한 형변환을 할 때는 그것이 사실인지(변수가 담은 객체의 실제타입) 검증하는 절차가 필요합니다. (검증절차 = 예외처리)
그 때 사용하는 키워드가 instanceof입니다. 이 키워드는 true/false의 값을 돌려주기 때문에 조건문에서 잘 쓰겠쥬?

위의 마지막 코드를 예로 들면. (변수a의 실제 내용이 B타입 객체인지 체크해라~~~ 시키려면)

if (a instanceof B){

                  b2 = (B)a;

} else{

}

이러한 예외 처리를 하는 이유는 프로그램이 에러를 만나 작업을 중단하는 일을 미연에 방지하기 위함입니다. 에러 만나면 그냥 넘기든지, 다른 명령을 내려줘야, 다음 코드들이 순차적으로 이어지겠죵?

 

* 주의사항: (B) 자리에 상속해준 부모 클래스 (A)를 넣어도 true를 리턴.

그 위 최초 조상 클래스 Object까지 다 true리턴. 

so, 여기서는 목적에 맞게 작은 범위를 지칭해서 해당 클래스 요소를 담고 있는지를 체크해야 합니다. 

 

 

아니, 다 좋은데 다형성을 왜쓰는거지?

다형성을 이용하면 매개변수parameter 값을 널널하게 잡아줄수 있고, 해당 매서드를 여기저기서 가져다 쓸 수 있습니다.

다형성 in 매개변수

29번째 줄에 (괄호) 안에 들어가 있는 매개변수 타입은 Goods타입(부모클래스)

실제 구현되는 44번 째 줄의 (매개변수)로 자식객체가 들어가 있는 걸 볼 수 있습니다.

 

또 다형성을 이용해서는 클래스를 확장해서 쓸 수 있습니다. 이 때 쓰는 게 오버라이딩입니다. 

다형성과 오버라이딩


33, 34줄) 메인 메서드에 보면 객체를 생성해서 paint() 메서드에 담아서 보내고 있습니다.

28줄) 매개변수 타입으로 부모클래스인 Shape를 지정해주고 있습니다. (그걸 상속받은 Line, Rect, Circle 그리고 자기자신 Shape도 매개변수에 들어갈 수 있게 됩니다.(다형성)

34) line 객체의(.) draw()메서드를 실행합니다.

35) Shape 객체의(.) draw()메서드를 실행합니다.

...

이런식으로 객체마다 동일한 이름의 메서드이지만 다른 기능을 수행하여 다른 결과를 낼 수 있게 되는 것이 오버라이딩으로 객체를 따로 정의해놓아서 가능한 것입니다.

 

다형성(오버라이딩) 구현의 예 - #linkedlist #링크트리스트 #링크드리스트

 



2. 추상클래스 : 개발의 밑그림이다~~ abstract


1) 개발할 때, 밑그림을 그리는 것. 프로그램 설계와 구현 중 설계에 해당하는 것입니다.
2) 키워드 : abstract
3) 추상메서드 : abstract 키워드를 붙여 메서드의 선언부만 있고,
구현부(중괄호{코드작성..}부분)은 되어있지 않습니다.

추상 클래스  일반 클래스
클래스 내부에 메서드 부분
abstract void func();
public abstract String getName();
public abstract void setName(String str); 
클래스 내부 메서드 부분
void func() { ... }
public String getName() { ... };
public void setName(String str){ ... }; 


4) 추상클래스 : 일반 멤버들과 함께 추상 메서드를 포함하는 클래스
추상메서드가 하나라도 있으면 무조건 추상 클래스가 됩니다.
클래스 앞에 abstract 붙여야합니다. // (메서드가 없어도 이걸 붙이면 추상클래스가 됨.. 메서드 없을바에 추상클래스 만들 필요는 없어서 거의 없지만..)

5) 추상클래스는 객체 생성이 불가합니다. 불완전한/ 미완성인 클래스라고 인식하니까 (구현부 없는 메서드 포함하니까 실행이 불가능..)

-> 상속받은 새로운 클래스로 객체를 생성합니다.

6) 상속에서 수퍼클래스로 사용됩니다. 필. 실제 클래스의 프레임으로 사용려는 목적이니까. 부모클래스가 될 수 있음. 킹키워드 extends

추상클래스 Calculator

상속받은 클래스 MyCalc
상속받은 클래스로 객체 생성 

7) 추상클래스를 물려받은 서브클래스를 완성시키려면, 
추상 메서드를 오버라이딩 한 후, 구현부{} 를 작성해서 일반 클래스로 만들어야 합니다. 
(구현하지 않는다면 그 클래스도 추상이되니까 abstract 또붙여야 - # 추상클래스 단순 상속)




3. 인터페이스 interface : 규격 호환성~~ implements / 일종의 추상클래스지만 차이가 있다~~


스프링 프레임워크는 내부가 인터페이스 기준으로 되어있어서 앞으로 인터페이스 만들어야
1) 키워드 : interface  //클래스가 아님. 클래스 대신 interface써.
interface PhoneInterface {
// 내용..
}
2) 인터페이스 멤버는 추상메서드와 상수(변치않는 값)만으로 구성된다.
일반변수와 일반메서드는 못들어감.
interface PoneInterface{
       public static final int BUTTONS = 20;  // 상수
       public abstract 리턴타입 메서드명(); //추상메서드만
       public abstract void receiveCall();
       public abstract void sendCall();
}
* 규격이니까 인터페이스 멤버는 누구나 다 접근 가능하게 전부 public을 붙여야 한다.

3) 모든 메서드는 public abstract 다 붙으니까, 생략 가능하다. 

4) 상수는 public static final이며, 생략 가능하다. 어차피 변수를 만든다면 그건 상수니까.
(static 객체 생성 없이도 쓸 수 있게끔. )


int BUTTONS = 20;  // 상수
리턴타입 메서드명(); //추상메서드만
void receiveCall();
void sendCall();

5) 인터페이스로 객체 생성 불가능. (new ~~ 안됨)
메서드는 모두 구현이 전혀 안된(미완성인) 추상메서드이므로...
6) 인터페이스로 레퍼런스변수 선언은 가능. 
PhoneInterface iPhone; (O)
.. new PhoneInterface(); (X)
7) 인터페이스 상속
인터페이스는 다른 인터페이스를 상속받을 수 있다.
인터페이스는 규격과 같은 것으로, 상속을 통해
기존 인터페이스에 새로운 규격을 추가한 새로운 인터페이스를 만들 수 있다.
다른 규격들을 상속받아서 많은 규격을 만들겠다는거지
extends 키워드 사용

interface MobilePhoneInterface extends PhoneInterface {
void sendSMS();
void recieveSMS();
}
추상보다 좋은 점은 인터페이스는 다중상속을 허용한다는 거! 뭔가 구현 만들어진게 없으니까 겹쳐도 된다...실행되다 충돌될일도 없어서
interface DualCameraPhoneInterface extends PhoneInterface, CameraInterface {
void makeVideo(); //자기것도 추가하고..
}

8) 인터페이스 구현 (사용하기)
: 인터페이스의 추상메서드를 모두 오버라이드로 구현한 클래스를 작성하는 것.

클래스를 만들어서 내부에 상속받은 추상메서드들을 {} 오버라이ㅣ드형태로 작성해요~~~
키워드 : (다르다.) implements 

ex) 모바일폰인터페이스로 아이폰 만들겠다 / 일반클래스로 객체를 생성.
class IPhone implements MobilePhoneInterface {
//추상 메서드를 모두 구현해좌야 한다.
원형이 public abstract 인데 구현에는 abstract빼야
public void sendCall() {...} 구현
public void receiveCall() {...}
상수까지 5개 중에 메서드4개만 구현하면 됨. 중괄호 내용물은 없어도 되니까 중괄호는 열어놔야.
public void sendSMS(){...}
public void receiveSMS(){...}
//추가적으로 일반 메서드나 변수 작성
public int getButtons() {...} 일반 메서드 추가 작성. 
}
* 추상 메서드 중 하나라도 구현을 안하면 에러!!!

9) 인터페이스의 목적 // 다형성의 하나. 아이폰은 객체 생성할 때 자기가 구현한 모바일 폰인터페잇의 자식으로 담을 수 있음. 규범만 주는 규격.......
내용은 다르게 돌아가지만 전화, 문자, 사진 등 모든 폰을 제어하기 쉬워짐. 다형성의 실행 도구중 하나가 인터페이스이다. 
설계, 가이드라인
다형성을 실현하는 도구
10) 인터페이스 좋은 점 다중 구현도 됨. (다중 상속 뿐만 아니라)
클래스는 하나이상의 인터페이스를 구현가능 ->
class IPhone implements MobilePhoneInterface {
//추상 메서드를 모두 구현해야 한다.

다중구현 다중상속 다되 . 확장성이 더 좋아. 한번에 클래스를 만들수있다는데........
그럼 추상클래스가 나은 경우는 내부 메서드말고 기본 더 가이드라인 주려고 할때



ArrayList 의 부모격 List 인터페이스 격체에. 느슨하게 호환. 범용으로 받게 개발   


그래서 인터페이스 구현해서 클래스 새로 잘 만들어놨어~ 근데 이걸 어따쓰나?

응 그 클래스로 객체를 만들어서 Thread객체 생성할 때 생성자 매개변수로 넘겨~~~~~~~






 

 

 

 

댓글