본문 바로가기

Contact 日本語 English

【Java】 5강. 다형성(polymorphism)

 

5강. 다형성(polymorphism) 

 

추천글 : 【Java】 Java 목차 


1. 개요 [본문]

2. signature [본문]

3. method overriding [본문]

4. hiding static variable [본문]

5. hiding static method [본문]

6. method overloading [본문]

7. operator overloading [본문]

8. generics [본문]


a. GitHub 


 

1. 개요 [목차]

⑴ 다형성 : 같은 기호를 쓰더라도 다른 변수, 명령어를 지칭하는 것

용어 1. up-casting

 

Parent parent = new Child();

 

① intrinsic casting과 explicit casting

 

Parent parent1 = new Child(); // Intrinsic Casting
Parent parent2 = (Parent) (new Child()); // Explicit Casting

 

② 필요성 1. 고정된 메모리를 할당하는 배열은 주소만 저장하므로 서로 다른 객체들의 배열을 만들 수 있음

 

Child[] cArray = new Child[2];
cArray[0] = new Son();
cArray[1] = new Daughter();

 

용어 2. down-casting 

 

Child child = (Child) new Parent(); // error

 

down-casting에서 Parent class가 Child class의 내용을 전부 담지 않으므로 강제 형변환이 불가능함

up-casting이 선행되었다면 Parent class가 Child class의 내용을 모두 가지므로 down-casting이 예외적으로 허용 

 용어 3. static binding 

① 정의 : 변수들의 타입이 컴파일 타임에 확정된 경우

② 컴파일 타임 : compiler가 binary로 변환할 때

③ 예 : privatefinalstatic 

용어 4. dynamic binding 

① 정의 : 변수들의 타입이 컴파일 과정에서 확정되지 않고 JVM의 runtime 중에 dynamic하게 할당되는 경우

② 즉, 실제로 프로그램을 돌려보면서 입력되는 거 보면서 어떤 function을 고를지를 결정하는 것

③ 즉, explicit type을 통해 해당 method가 있는지 확인하고, runtime에서 수행할 때 실제 object의 method 호출

④ 예 : method overriding, equals()toString()hashCode() 

용어 5. object type casting 

① 목적 : 메모리 내 저장된 정보가 있어도 type definition에 따라 접근할 수 없을 수 있어서 강제 형변환이 필요함

 explicit type을 따라가는 경우 (hiding) : static method, attribute, method parameter

③ actual type을 따라가는 경우 (overriding) : instance method 

④ (참고) static method : hiding static method와 관련

⑤ (참고) attribute : hiding static variable과 관련

 

 

2. signature [목차]

① 개요

○ 정의 : 함수를 호출 시 식별자로 사용되는 요소

○ compile time에 결정됨

② C : 함수의 이름

○ C에서 동일한 이름을 가진 method를 동시에 선언할 수 없음

③ java : method name, parameter format

○ java에서 동일한 이름을 가진 method를 동시에 선언할 수 있음

○ return type은 signature가 아님 : return type이 다르면 java compiler는 에러를 일으킬 수 있음

 

int add(int, int);
double add(int, int); // compile error

 

○ signature는 explicit type을 기준으로 함 (ref)]

 

 

3. method overriding [목차]

⑴ 개요

① 정의 : child class에서 새롭게 정의된 method가 parent class에서 받은 inherited method를 덧쓰는 것

② variable은 overriding 개념이 아니라 hiding 개념이 적용됨

③ (출제 예상) 예제

 

class Parent {
    int x = 1;
    void print(){System.out.println("Parent");}
}
class Child extends Parent {
    int x = 2;
    void print(){System.out.println("Child");}
}
public class Main {
    public static void main(String[] args) {
        Child child = new Child();
        Parent parent = (Parent) child;
        System.out.println(parent.x);   // 1
        parent.print(); // Child
    }
}

 

⑵ 요건

① child class가 parent class로부터 상속을 할 것

② child class의 method와 parent class의 method의 signature가 같을 것

③ child class의 method와 parent class의 method의 return type이 같을 것

④ parent class의 method가 publicprotecteddefault일 것 

private의 경우 child class에서 invisible하기 때문

default라고 해도 package가 다르면 child class에서 invisible하기 때문에 상속되지 않음

○ 일반적으로 object method는 대부분 public

○ (출제 예상.clone()과 .finalize()는 private 

⑤ parent class의 method가 non-static일 것 : static이면 overriding이 아니라 hiding이 적용됨

⑶ 문법

① constructor overriding은 허용되지 않음 

② typo 방지 

○ child class에서 @override를 추가해서 typo를 방지할 수 있음 (선택)

○ parent class에 abstract를 쓰면 child class에서 override할 것이라는 계약을 하게 됨  

overriding method가 overridden method보다 같거나 더 넓은 범위여야 함

overridden method가 public이면 overriding method는 public이어야 함

overridden method가 protected이면 overriding method는 protected 또는 public이어야 함 

private 또는 static method는 overridden method가 될 수 없음

예제 1 : method overriding은 parent.print();와 관련

 

class Parent {
    int x = 1;
    void print(){System.out.println("Parent");}
}
class Child extends Parent {
    int x = 2;
    void print(){System.out.println("Child");}
}
public class Main {
    public static void main(String[] args) {
        Child child = new Child();
        Parent parent = (Parent) child;
        System.out.println(parent.x);   // 1
        parent.print(); // Child
    }
}

 

예제 2

 

public class Main{
    public static void main(String[] args){
        A a1 = new A();
        A a2 = new B();
        A a3 = new D();

        a1.m2();    // "A.m2"
        a2.m2();    // "B.m2"
        a3.m2();    // "C.m2"
        ((B) a2).m1();  // "B.m1"
        // a2.m1() is error
    }
}

class A{
    public void m2(){
        System.out.println("A.m2");
    }
    public void m3(){
        System.out.println("A.m3");
    }
}

class B extends A{
    public void m1(){
        System.out.println("B.m1");
    }
    public void m2(){
        System.out.println("B.m2");
    }
}

class C extends A{
    public void m2(){
        System.out.println("C.m2");
    }
    public void m3(){
        System.out.println("C.m3");
    }
}

class D extends C{
    public void m1(){
        System.out.println("D.m1");
    }
    public void m3(){
        System.out.println("D.m3");
    }
}

 

 

4. hiding static variable : variable hiding, variable shadowing이라고도 함 [목차]

⑴ 개요

① 정의 : object type casting에서 variable이 explicit type을 따라가는 것

② (주석) 굳이 static일 필요는 없는 듯

③ variable은 method와 달리 overriding이 아니라 hiding의 개념이 적용됨

예제 1 

 

class P1 {
  static int x = 2;
}

class P2 extends P1 {
  static double x = 3;
  void print() {
    System.out.println(x + " " + super.x + " " + ((P1) this).x);
  }
}

public class Main {
  public static void main(String[] args){
    P2 p = new P2();
    p.print();
    // 3 2 2
  }
}

 

① hiding static variable은 구체적으로 ((P1) this).x와 관련 

② parent class에서 선언한 static 변수에 대하여, 

○ child class에서 같은 이름으로 다시 선언 시 : 상속이 일어나지 않음

○ parent static 변수인 x = 2는 p의 메모리에 저장돼 있음

○ child class에서 x = 3을 선언하지 않았을 시 : child object는 parent class의 static 변수를 상속

③ 위와 같은 논리는 non-static variable, static method에도 적용됨

예제 2 

 

class A{
  int a = 0;  public void add() { a++; }
}
class AA extends A{
  int a = 14;
} 
class B{
  int b = 0;  public void add() { b++; }
}
class BB extends B{
  int b = 14;  public void add() { b++; }
}
public class Main{
  public static void main(String[] agrs){
    AA a = new AA();
    BB b = new BB();
    a.add();  b.add();
    System.out.println(a.a);  // 14; hidden a = 1
    System.out.println(b.b);  // 15; hidden b = 0
  }
}

 

① method는 일단 같이 있던 variable에 우선순위를 부여함

② (참고) 실제로 JVM은 current class에서 먼저 찾아보고 없으면 parent class, grandparent class, ... 순으로 탐색

 

 

5. hiding static method [목차]

⑴ 개요

① 정의 : object type casting에서 static method가 explicit type을 따라가는 것

예제 1 

 

class Super{
  static String greeting() { return "Goodnight"; }
  String name() { return "Richard"; }
}

class Sub extends Super {
  static String greeting() { return "Hello"; }
  String name() { return "Henry"; }
}

public class Main {
  public static void main(String[] args){
    Super s = new Sub();
    System.out.println(s.greeting() + ", " + s.name());
    // Goodnight, Henry
  }
}

 

Sub class를 생성하는 과정에서 greeting()은 parent method와 child method가 공존함 (hiding)

② Sub class를 생성하는 과정에서 name()은 덧씌여짐

예제 2  

 

class Parent {
    int x = 1;
    static void print1(){System.out.println("Parent1");}
    void print2(){System.out.println("Parent2");}
}
class Child extends Parent {
    int x = 2;
    static void print1(){System.out.println("Child1");}
    void print2(){System.out.println("Child2");}
}
public class Main {
    public static void main(String[] args) {
        Parent person = new Child(); 
        System.out.println(person.x); // 1
        person.print1(); // Parent1
        person.print2(); // Child2
    }
}

 

 

6. method overloading [목차]

⑴ 개요

① 정의 : 동일한 method name, return type, 다른 parameter type인 경우

② 목적 1. 서로 다른 data type으로 같은 task를 처리하기 위해

③ 목적 2. 자료형에 따라 약간 다르게 처리하기 위해

⑵ 문법 : overloaded method를 override하는 게 가능

⑶ 예제 (추후 업데이트)

 

 

7. operator overloading [목차]

argument type에 따라 +, *, &, % 등의 연산자가 다른 의미를 갖는 것

⑵ java는 user-driven operator overloading을 제공하지 않음

⑶ 예 

 

String s = "Dog" + " barks.";
s += "Too Loud!";
float f = 0.5 % 0.3;

 

 

8. (출제 예상) generics [목차]

⑴ 개요

① 정의 : 하나 이상의 변수 타입을 정의하는 클래스. parametric polymorphism

장점 : robustness, no type casting

문법

generic class : class C<T1, ..., Tn>

 

class Wrapper<T> { 
  T obj;
  void add(T obj) { this.obj = obj; }
  T get() { return obj; }
}

 

T는 symbol에 불과함 : T뿐만 아니라 E도 많이 쓰임

T는 아무 타입이 될 수 있으나 primitive type이 될 수 없음 

○ T에 특정한 타입이 오도록 한정할 수 있음

T t = new T(); 같은 느낌은 안됨 : 컴파일 타임에 해당 생성자 유무를 확인할 수 없으므로

② generic method

 

class ArrayPrinter {
  public static <E> void printArray(E[] elements) {
    for(E element : elements) {
      System.out.print(element.toString() + " ");
    }
  }
}

 

○ generic이 올 것임을 예고하는 <E> 등이 public static final 등 이후에 옴 

③ generic constructor 

 

public <T> Main (T t) { ... }

 

○ generic이 올 것임을 예고하는 <E> 등이 public static final 등 이후에 옴 

④ wildcards in generic

○ <? extends T> : T 또는 T의 sub type을 이용 

○ <?> : Object 또는 Object의 sub type을 이용

○ <? super T> : T 또는 T의 super type을 이용

⑤ generic는 class든 interface든 모두 extends로 작성

T implements Comparable<T>가 아니라 T extends Comparable<T> 

 

입력: 2020.09.23 17:34

'▶ 자연과학 > ▷ Java' 카테고리의 다른 글

【Java】 6강. 자료구조  (0) 2020.10.20
【Java】 Java 목차  (0) 2020.09.23
【java】 4강. 상속(inheritance)  (0) 2020.09.23
【Java】 3강. 캡슐화  (0) 2020.09.23
【Java】 2강. 클래스  (0) 2020.09.23