자바
[자바] 다형성
j9972
2022. 8. 6. 13:13
728x90
다형성 - 하나의 메소드나 클래스가 있을때 다양한 방법으로 동작하는 것을 의미한다
다형성의 쉬운 예제는 오버로딩이다. ( 같은 이름 동작 방법 )
class O {
public void a(int param) {
System.out.println(param);
}
public void a(String param) {
System.out.println(param);
}
}
public class polyDemo {
public static void main(String[] args) {
O o = new O();
o.a(10);
o.a("ten");
}
}
클래스와 다형성
class A {
public String x() {
return "x";
}
}
class B extends A {
// 오버라이딩 -> 부모클래스보다 우선순위가 높다
public String x() { return "B.x"; }
public String y() {
return "y";
}
}
public polyDemo {
public static void main(String[] args) {
A obj = new B(); // B의 인스턴트가 A의 형태를 한다
// obj의 데이터 타입은 A 이다
obj.x();
obj.y(); // 얘 때매 오류남
// obj.x(); -> x가 아닌 B.x가 출력된다
}
}
여기에서 알아야 할 것
1. 어떤 클래스를 인스턴스화 할때, 인스턴스를 담는 변수의 데이터 타입은 그 클래스(B)가 될수 있고, 부모클래스(A)가 될 수 있다
효과 ) 인스턴스가 부모클래스인 A처럼 동작을 할 수 있다.
쓰는 이유) 오버라이딩하면 부모가 아닌 오버라이딩한 메소드가 있는 클래스의 메소드가 호출된다 ( B )
실전예제
부모클래스데이터타입 참주변수 = new 자식클래스데이터타입
abstract class Cal {
int left, right
public void setOprands(int left, int right) {
...
}
}
public class CalDemo {
public static void main(String[] args) {
// 다형성 추가 x
CalPlus c1 = new CalPlus();
// 다형성 추가 o
Cal c1 = new CalPlus();
c1.setOprands(10,20);
c1.run(); // sum, avg메소드
// 다형성 추가x
CalMinus c2 = new CalMinus();
// 다형성 추 가 o
Cal c1 = new CalMinus();
c2.setOprands(10,20);
c2.run();
}
}
// 조금더 다형성 추가
abstract class Cal {
int left, right
public void setOprands(int left, int right) {
...
}
}
public class CalDemo {
public static void execute(Cal cal) {
cal.run(); // 부모클래스의 sum, avg 메소드를 실행시켜준다
}
/*다형성 추가 x -> 코드 중복
public static void execute(CalPlus cal) {
cal.run(); // 부모클래스의 sum, avg 메소드를 실행시켜준다
}
public static void execute(CalMinus cal) {
cal.run(); // 부모클래스의 sum, avg 메소드를 실행시켜준다
}
public static void main(String[] args) {
CalPlus c1 = new CalPlus();
CalMinus c1 = new CalMinus();
}
*/
public static void main(String[] args) {
Cal c1 = new CalPlus();
c1.setOprands(10,20);
Cal c1 = new CalMinus();
c2.setOprands(10,20);
execute(c1);
execute(c2);
}
}
인터페이스와 다형성
기본 예시 코드
interface I {}
class C implements I {}
public class polyDemo {
public static void main(String[] args) {
I obj = new C();
}
}
설명
클래스 C가 인스턴스화가 될때 데이터 타입이 I 가 될 수 있는 이유는 C가 I를 구현하기 때문이다.
new 예시
interface I2 {
public String A();
}
interface I3 {
public String B();
}
class D implements I2, I3 {
public String A() {
return "A";
}
public String B() {
return "B";
}
}
public class polyDemo {
public static void main(String[] args) {
D obj = new D(); // ( 모든 기능을 쓰고 싶다면 이렇게 해야함 )
I2 objI2 = new D(); // 특정 기능만 사용하겠다
I3 objI3 = new D();
obj.A(); // class D를 가져오기에 모두 사용 가능
obj.A();
objI2.A(); // I2는 A메소드만, B호출시 에러
objI3.B();
}
}
쉬운 예시
개발자를 고용하는데 있어서 특정 기능 ( 코딩을 하는 스타일 ) 이 궁금하지, 모든 기능 ( 코딩 스타일 + 가족관계 ) 모두가 필요한건 아니다.
위의 설명 바탕의 코드
interface father{}
interface mother{}
interface beliver{}
interface programmer{
public void coding();
}
class Steve implements father, programmer, believer {
public boid coding() {
System.out.println("fast");
}
}
class Rachel implements mother, programmer {
public boid coding() {
System.out.println("elegance");
}
}
public class workspace {
public static void main(String[] args) {
progrmmer employee1 = new Steve();
progrmmer employee2 = new Rachel();
employee1.coding();
employee2.coding();
}
}
구체적으로, 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 한다.
Tv t = new Tv();
CaptionTv c = new CaptionTv();
지금까지는 생성된 인스턴스를 다루기 위해서는 인스턴스의 타입과 일치하는 타입의 참조변수만을 사용했다.
즉, Tv 인스턴스를 다루기 위해서는 Tv타입의 참조변수를 사용하고, CaptionTv 인스턴스를 다루기 위해서는 CaptionTv타입의 참조변수를 사용했다.
Tv t = new CaptionTv();
하지만, 상속의 경우에는 조상 클래스 타입의 참조변수로 자손 클래스의 인스턴스를 참조가 가능하다.
주의!
CaptionTv c = new CaptionTv();
Tv t = new CaptionTv();
실제 인스턴스가 CaptionTv타입이라 할지라도, 참조변수 t로는 CaptionTv인스턴스의 모든 멤버를 사용할 수 없다.
( CaptionTv 인스턴스 중에서 Tv 클래스의 멤버들 ( 상속받은 멤버포함 ) 만 사용이 가능하다. CaptionTv의 것은 사용 불가능 )
-> Tv : power(), power, channel, channelUp(), channelDown()
-> CaptionTv : power(), power, channel, channelUp(), channelDown(), text, cpation()
여기서는 text랑 caption() 사용이 불가능
둘 다 같은 타입의 인스터스지만 참조변수의 타입에 따라 사용할 수 있는 멤버 개수가 다르다.
조상타입의 참조변수로 자손타입의 인스턴스를 참조할 수 있다.
반대로 조상타입의 참조변수로 조상타입의 인스턴스를 참조할 수 없다.