[JAVA] 제어자(modifier)와 다형성(polymorphism)

    제어자

    클래스, 변수, 또는 메서드의 선언부에 함께 사용되어 부가적인 의미를 부여한다.

    접근 제어자 : public, protected, default, private

    그 외 제어자: static, final, abstract 등

    final

    final 클래스: 변경될 수 없고 확장될 수 없는 클래스, 다른 클래스의 조상이 될 수 없다.

    final 메서드: 변경될 수 없고 오버라이딩을 통해 재정의 될 수 없다.

    final 멤버변수, 지역변수: 값을 변경할 수 없는 상수가 된다.

     

    public class Card {
        final int NUMBER; // (1)
        final String KIND;  // (1)
        
        static int width = 100;
        static int height = 250;
    
        public Card(int num, String kind) {
            NUMBER = num;
            KIND = kind;
        }
    }

     

    public class Test {
        public static void main(String[] args){
            Card card = new Card(3,"Heart"); // (2)
    //        card.NUMBER = 10; // (2)
        }
    }

     

    (1) 인스턴스변수의 경우 선언과 함께 초기화하지 않고 생성자에서 초기화 되도록 할 수 있다.

    (2) 생성자에서 단 한 번만 초기화 할 수 있다.

     

    접근 제어자(access modifier)

    2022.11.27 - [JAVA] - [JAVA] 객체 지향의 4가지 특징

     

    [JAVA] 객체 지향의 4가지 특징

    OOP 객체지향이론의 기본 개념은 '실제 세계는 사물(객체)로 이루어져 있으며, 발생하는 보든 사건들은 사물 간의 상호작용이다' 라는 것이다. 객체지향 프로그래밍 패러다임은 어떤 개념에 대한

    dev-daybyday.tistory.com

     

    생성자의 접근 제어자

    public class Singleton {
    
        private static Singleton singleton = new Singleton();
        
        private Singleton(){}
        
        // 인스턴스를 생성하지 않고도 호출할 수 있어야 하므로 static
        public static Singleton getInstance(){
            return singleton;
        }
    }

     

    2022.10.05 - [JAVA] - [JAVA] 싱글톤 패턴 정리

     

    [JAVA] 싱글톤 패턴 정리

    싱글톤 패턴이란? 싱글톤 패턴(Singleton pattern)을 따르는 클래스는, 생성자가 여러 차례 호출되더라도 실제로 생성되는 객체는 하나이고 최초 생성 이후에 호출된 생성자는 최초의 생성자가 생성

    dev-daybyday.tistory.com

     

    생성자가 private인 클래스는 다른 클래스의 조상이 될 수 없다. 자손 클래스가 인스턴스를 생성할 때 조상 클래스의 생성자를 호출해야 하는데 (super();) 생성자의 접근 제어자가 private이면 호출이 불가능하기 때문이다.

    그래서 클래스 앞에 final을 추가하여 상속할 수 없는 클래스임을 알리는 것이 좋다.

     

    private 메서드에는 final 추가할 필요 없다. private 만으로도 오버라이딩 될 수 없다는 의미가 충분하기 때문이다.

    다형성

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

    조상 클래스 타입의 참조변수로 자손 클래스의 인스턴스를 참조할 수 있는 것

    public class Tv {
        boolean power;
        int channel;
    
        public void channel(int channel) {
            System.out.println(channel);
        }
    }
    
    
    public class CaptionTv extends Tv{
        String text;
    
        public void text(String text) {
            System.out.println(text);
        }
    }

     

    public class Test {
        Tv tv = new CaptionTv(); // (1)
        CaptionTv captionTv = new CaptionTv(); // (2)
    }

     

    (1) 조상 타입의 참조변수로 자손 인스턴스를 참조, tv는 CaptionTv 인스턴스의 모든 멤버를 사용할 수 없다.

    (1), (2) 둘 다 같은 타입의 인스턴스지만 참조변수의 타입에 따라 사용할 수 있는 멤버의 개수가 달라진다.

     

    참조변수가 사용할 수 있는 멤버의 개수는 인스턴스의 멤버 개수보다 같거나 적어야 한다.

    따라서 자손 타입의 참조변수로 조상 타입의 인스턴스를 참조할 수 없다.

     

    형변환

    Up-casting: 자손타입 -> 조상타입: 형변환 생략 가능

    Down-casting: 조상타입-> 자손타입: 형변환 생략 불가

     

    형변환은 참조변수의 타입을 변환하는 것이지 인스턴스를 변환하는 것이 아님

    참조변수의 형변환을 통해 참조하고 있는 인스턴스에서 사용할 수 있는 멤버의 개수를 조절하는 것 뿐

    참조변수가 가리키는 인스턴스를 형변환시킬 수 없으므로 참조변수가 가리키는 인스턴스를 확인하는 것이 중요

     

    public class Test {
        public static void main(String[] args){
            CaptionTv ctv = new CaptionTv();
            Tv tv = new Tv();
            Tv tv2 = new CaptionTv();
    
            ctv.text("caption1");
    //        CaptionTv ctv2 = (CaptionTv) tv; // (1)
    //        tv2.text(); 	// (2)
            tv = ctv; 		// (3)
            CaptionTv ctv2 = (CaptionTv) tv; // (4)
            ctv2.channel(11);
            ctv2.text("captiontv"); //(5)
        }
    }

    (1) 자손 타입의 참조변수 ctv2로 조상 타입의 인스턴스를 참조할 수 없다. (런타임 에러)

    (2) 자손 인스턴스를 참조하고 있지만 조상 타입의 참조변수로는 자손클래스에만 정의되어 있는 text()를 호출할 수 없다. (컴파일 에러)

    (3) tv = (CaptionTv) ctv : up-casting

    (4) down-casting

    (5) 자손 참조변수 타입으로 자손 타입 인스턴스를 참조하므로 text() 호출 가능

     

    instanceof 연산자

    public class Test {
        public static void main(String[] args){
            Tv c = new CaptionTv();
            Tv t = new Tv();
            instance(c);
            instance(t);
    
        }
        static void instance(Tv t){
            if(t instanceof CaptionTv){
                System.out.println("This is instance of CaptionTv");
            }else{
                System.out.println("This is instance of Tv");
            }
        }
    }

    실행 결과:

    This is instance of CaptionTv
    This is instance of Tv

     


    참고: 자바의 정석 - 남궁성

     

    🤞자바의 정석 스터디 5,6일차 p336-374🤞

     

     

     

    728x90

    'JAVA' 카테고리의 다른 글

    [JAVA] Collections Framework 인터페이스  (0) 2022.12.12
    [JAVA] 인터페이스  (0) 2022.12.08
    [JAVA] 오버라이딩 (overriding)  (0) 2022.12.03
    [JAVA] 생성자와 변수의 초기화  (0) 2022.12.01
    [JAVA] 메서드(Method)  (0) 2022.11.30

    댓글