본문 바로가기

Java 기본 개념

자바를 잡아라 제13장 - '나'라는 객체가 여러 형태를 갖는 날까지...

728x90

 

 

다형성(Polymorphism)
: 팔방미인 그 잡채

 

 

 

다형성이란
'객체가 여러 형태를 가진다' 라는 의미로 해석되며,
하나의 객체가 여러가지 유형으로

사용되는 것을 의미합니다

 

 

 

 

 

   [ 다형성의 특징 ] 

 

 

       상속은 전제조건

       자식클래스가 부모클래스의 타입을 가질 수 있도록 허용한다. 

       ( 즉, 부모 타입에 모든 자식 객체가 대입될 수 있다 )

 

 

 

 

 

 

 

 

   Student, Teacher, Employee(자식클래스)로

   생성해서 Person(부모) 타입에 저장할 수 있다

 

   부모에 있는 메서드만 실행가능하며

   overriding 메서드는 우선 실행된다

 

 

 

 

 

 

 

 

 

 

강제 타입 변환 (Type Casting)
: 다른 것을 같게

 

 


강제 타입 변환부모 타입을 자식 타입으로 변환하는 것을 말한다

객체에서 타입 캐스팅을 사용하려면 우선 먼저 Promotion이 일어나야 한다

즉, 부모 타입으로 한번 형 변환이 된 자식 객체만 강제 타입 변환을 사용 할 수 있다

 

  [ promotion과 casting의 차이]

     promotion작은 값을 큰 곳으로 옮기는 것을 의미하고 casting큰 값을 작은 곳으로 옮기는 것을 의미함


Promotion이 일어나면 자식 클래스가 가지고 있는 재정의(오버라이딩)되지 않은 메서드를 사용할 수 없다는 단점이 있다

이 단점을 극복하기 위해 강제 타입 변환(Type Casting)을 사용하여 자식 메서드를 호출하는 방법을 사한다

                                       (업 캐스팅 했던 걸 다시 원래대로 돌려놓는 것)

 

 

 

 

 

          먼저 Child(자식 클래스)는

          Parent(부모 클래스)에

          묵시적으로 변환이 일어남

 

          클래스 타입의 형 변환(명시적) 가능

                >> Child 타입의 기능 사용 가능

 

 

 

 

 

 

 

 

이종모음 (Heterogeneous Collection)

 


   이종모음은 배열에 다형성을 적용시키는 원리이다 (배열은 원래 동종모음 구조)

   예를 들어 int [ ] iArr = new int [10]; 이런 구조의 배열이 있다면 iArr 배열에는 int형 정수 데이터만 저장할 수 있다

   하지만 다형성을 이용하면 이종모음 구조의 객체 배열이 생성 가능하다

 

 

 

 

 

 

    부모 타입 배열인 pArr에 자식 객체가 저장

     즉, pArr이라는 배열안에 요소로

       (홍길동, 20)

       (허현수, 17, 2016001)

       (허현준, 22, Java programming)

       (허현정, 23, 교무처)

       이 순서대로 저장된다

 

 

 

 

 

 

 

 

 

매개 변수의 다형성 

 

 

   promotion은 멤버 변수의 값을 대입할 때도 발생하지만, 메서드를 호출할 때 사용하는 매개 변수에도 발생할 수 있다

   보통 메서드를 호출할 때는 메서드 선언부에서 지정한 데이터 타입과 일치하는 매개값을 전달하여 호출하지만,

   매개 변수에 다형성을 적용하면 자식 객체를 전달할 수도 있다

 

 

 

 

 

 

 

  매개변수에 객체를 전달하려면

  타입을 클래스 타입을 적어주면 된다

 

   그렇게 되면

   Person의 자식 클래스는

   전부 전달된다

 

 

 

 

 

 

 

 

 

 

instanceof 키워드

 


    객체가 지정한 클래스의 인스턴스인지 아닌지 검사할 때 사용하는 연산자이다 (클래스에만 적용 가능)

   

    [ 객체 레퍼런스 instanceof 클래스 타입 ]

    instanceof 연산자의 왼쪽 항의 객체가 오른쪽 항 클래스의 인스턴스(=오른쪽 항의 객체)라면

    true를 리턴하고, 그렇지 않으면 false를 리턴한다

 

 

 

 

 

 

 

 

 

 

  Person p = new Student ( );

  p instanceof Student   >>  true

  (Person 클래스의 p가

  Student라는 클래스 타입이 맞다라는 의미)

 

 

 

 

 

 

 

 

 

 

 

 

사용 제한자 (Usage Level modifier)

 

 

      static의 특징


   

       변수, 메서드에 적용되는 자바의 키워드로 static 메서드나 변수는 해당 클래스의 객체 없이도 참조할 수 있다

       static 블록 ( static 메서드, 정적 초기화자 ) 안에는 static 변수 사용해야 하고 , static 메서드 호출할 수 있다

       (즉 static 블록에서 non static 멤버를 객체 생성 없이 직접 참조할 수 없다)
 
       static 제한자는 지정된 변수와 메서드를 객체와 무관하게 만들어주기 때문에 this를 가질 수 없다
       static 메서드는 non static 메서드로 재정의 ( Overriding ) 될 수 없다
       (대표적인 static 메서드는 애플리케이션의 main () 메서드)

       static에 단순히 블록 ({ 을 사용한 경우에는 정적 초기화자라고 부르며 , static 변수를 초기화하는 역할을 가지고 

       클래스가 로딩될 때 main () 메서드가 있더라도 그보다 앞서 딱 한번 실행

 

       만약 일반변수를 사용하지 않고 범용성 있게 사용할 메서드라면 static을 선언하면 다른 객체에서 접근하기 좋다

 

 

 

 

 

 

 

정적 변수 static field

 

 

    static 변수는 모든 객체들이 공유하는 공유변수가 된다

 

    정적 변수는 객체를 만들어 참조할 수도 있지만 , 객체를 만들지 않고 클래스 이름만으로도 참조가 가능하기 때문에

    이를 클래스 변수라고도 부릅니다

 

 

 

 

정적변수와 정적변수가 아닌 변수의 차이

 

 

 

   

    1)  a의 경우 static으로 선언되지 않았기 때문에 객체가 반드시 생성되어야 하지만

          b의 경우 객체의 생성여부는 중요하지 않다

 

    2)  a의 경우체간 공유가 없기 때문에 b와 달리 값에 변동이 없고

          b는 정적변수로 객체간 공유가 이루어져서 값이 변동되었다

 

    3)  변수 b는 static으로 선언되었기에 별도의 객체 생성 없이 클래스 이름(Count).b

         사용될 수 있으며 b는 모든 객체가 공유하기 때문에 모두 3으로 값이 동일하다

 

 

 

 

 

 

 

 

 정적 메서드(static method)

 

   

   static 메서드는 static 변수와 마찬가지로 해당 클래스의 객체 생성 없이도 참조가 가능하게 해준다

 
   멤버를 참조할 때 주의해야 할 사항은 "static 메서드 안에서는 non-static 멤버를 객체 생성 없이 직접 참조할 수 없다"는 것
   ( static 메서드 안에서는 static 변수를 선언할 수 없다 )

 

 

 

 

 

 

Count 클래스 내부에서

정적변수가 아닌 a와 정적변수인 b를 선언하였고

doIt()이라는 정적 메서드를 생성 및 선언을 했다

이 때 변수 a는 doIt이라는 메서드에서 접근이 불가능

반면 b는 선언이 참조가 가능하다

 

static은 특성상

static으로 선언된 메서드나 변수는 상호간의 참조는 가능하나

static으로 선언되지 않은 경우에는

반드시 객체 생성이 별도로 이루어져야만 참조가 가능하다

 

따라서 위의 경우 a가 메서드 안에서 사용하려면

Count c1 = new Count();라는 객체를 생성하고 c1.a로 바꾸면 된다

 

 

 

 

 

 

 

 

정적 초기화자(static initializer)

 

 


     정적 초기화자는 static 변수들의 초기화에 사용한다

     일반 멤버변수는 생성자에서 초기화하지만 static 변수는 객체 생성 없이도 사용해야하므로 생성자를 통해 초기화할 수 없다
     그렇기 때문에  static 변수는 정적초기화자를 통해 초기화를 해야 한다


     정적 초기화자는 클래스가 로딩될 때 생성자와 main() 메서드에 앞서 오직 단 한번만 실행되기 때문에

     애플리케이션 실행 중 반드시 한번만 실행되어야 할 로직이 있다면 이곳에 기술하여 사용될 수 있다.

 

 

 

 

 

 

 

   [ 자바에서 static이 갖는 의미 ]


     1. static멤버는 객체 생성 없이 클래스명.이름 으로 참조 가능
     2. static변수객체간 값의 공유의 의미
     3. static메서드같은 static멤버만 참조가능 (클래스명.이름 으로 참조)

     

 

       < static메서드의 대표적인 사용 >


             Math.random();
             Arrays.toString(배열명);
             Integer.parseInt(문자열);

 

 

 

 

 

 

싱글톤 패턴(Singleton Pattern)

 

   생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는

   최초의 생성자가 생성한 객체를 리턴한다 (객체를 전역적으로 사용 가능)

   싱글톤 패턴은 객체의 생성을 제한하기 위해 사용한다 (자바를 이용한 프로그래밍에서 사용됨)

 

 

 

 

 

 

 

 

 

 지금까지의 내용을 다음 예제를 통해 확인해보자

 

 

 

  1) Arrays.toString( )의 기능 따라잡기

 

 

 

  ① String 타입으로 반환되고 매개변수가 int 배열인 toArray 메서드

  ② String 타입으로 반환되고 매개변수가 char 배열인 toArray 메서드

  ③ String 타입으로 반환되고 매개변수가 String 배열인 toArray 메서드

  호출할 때, Constructor를 생성하지 않고

  클래스 이름(PrintArray).메서드 이름(매개변수)로 호출(static의 전형적인 모습)

   

 

 

 

 

 

 

   2) static으로 선언된 멤버, 메서드간의 상호 관계 알아보기

 

 

 

 

      [1]  Count 클래스에서 일반변수 a정적변수 b를 선언

 

 

            ① 일반 메서드인 some1( ) 선언

 

                 일반 변수인 a정적 변수인 b 모두 사용 가능

 

 

            ② 정적 메서드인 some2( ) 선언

           

                정적 변수인 b당연히 사용이 가능하지만 일반 변수인 a의 경우에는 바로 사용이 불가능하다

                일반 변수도 정적 메서드 내부에서 사용이 가능하나 이 경우는 반드시 객체를 생성을 통해 사용해야 한다

 

  

 

 

         [2]  ain 클래스를 통해 정적 메서드와 일반 메서드 호출

 

 

              ① 일반 메서드인 some1( ) 호출

 

                일반 메서드의 경우는 반드시 객체 생성을 한 다음에야 비로소 호출이 가능하다

                (Main클래스가 static으로 선언되어 있기 때문에)

 

 

            ② 정적 메서드인 some2( ) 호출

  

               정적 메서드의 경우는 객체 생성을 통해 메서드를 호출해도 무방하고 

               객체 생성 없이 바로 클래스를 참조하여 사용하는 것도 가능하다

 

 

            ③ Main 클래스에서 b의 값 출력

 

             some1()과 some2() 모두 ++b를 리턴하고 메서드가 3번이 호출되었고 생성된 객체가 다르더라도

             static 변수는 모든 객체가 공유를 하기 때문에 b의 값은 3이 출력된다

 

 

 

 

 

 

   3) 싱글톤 패턴 익히기

 

 

 

정적초기화자

 

 

 

  [1] Singleton 클래스의 내부

 

   싱글톤 패턴이라는 게 객체가 무한 생성되는 것을 막기 위한 것으로 단 하나의 객체를 활용해 설계를 하는 것이다

   나 자신 객체 1개를 멤버변수로 선언하고 외부에서 객체 생성을 하지 못 하도록 기본 생성자를 private로 선언하였다

   멤버변수는 static으로 선언되어 외부에서 접근이 불가능하기 때문에 getter메서드를 통해 접근이 가능하다

 

 

  [2] Main 클래스의 내부

 

   Singleton 클래스 내부의 static으로 선언된 getter메서드를 객체 생성 없이 바로 사용하고 있다

   이 때 getter 메서드를 3번을 사용하였는데 이는 모두 하나의 인스턴스로 인식한다