자바 9일차

김재현·2022년 8월 8일
0

Java

목록 보기
10/15

캡슐화와 접근 제어자

  • 클래스의 내부에 선언된 데이터를 보호하기 위해서 접근제어자를 사용한다.
    데이터가 유효한 값을 유지하도록, 데이터를 외부에서 함부로 변경하지 못하도록 하기 위해서는 외부로부터의 접근을 제한하는 것이 필요하다.
    이것을 데이터 감추기(data hiding)라고 하며, 객체지향개념의 캡슐화(encapsulation)에 해당하는 내용이다.
  • 다른 이유는 클래스 내에서만 사용되는, 내부 작업을 위해 임시로 사용되는 멤버변수나 부분작업을 처리하기 위한 메서드 등의 멤버들을 클래스 내부에 감추기 위해서다.
    외부에서 접근할 필요가 없는 멤버들을 private로 지정하여 외부에 노출시키지 않음으로써 복잡성을 줄일 수 있다. 이것 역시 캡슐화에 해당한다.

    접근 제어자를 사용하는 이유
    1) 외부로부터 데이터를 보호하기 위해서
    2) 외부에는 불필요한, 내부적으로만 사용되는, 부분을 감추기 위해서

  • 만일 상속을 통해 확장될 것이 예상되는 클래스라면 멤버에 접근 제한을 주되, 자식 클래스에서 접근하는 것이 가능하도록 하기 위해 private 대신, protected를 사용한다.
  • 보통 멤버변수의 값을 읽는 메서드의 이름을 get멤버변수이름으로 하고, 멤버변수의 값을 변경하는 메서드의 이름을 set멤버변수이름으로 한다. 암묵적인 규칙이므로 특별한 이유가 없는 한 따르자.
    get으로 시작하는 메서드를 '게터(getter)', set으로 시작하는 메서드를 '세터(setter)'라고 한다.

다형성(polymorphism)

  • '여러가지 형태를 가질 수 있는 능력'을 의미.
    자바에서는 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 함으로, 다형성을 프로그램적으로 구현하였다.
  • 부모 클래스 타입의 참조변수로 자식클래스의 인스턴스를 참조할 수 있도록 하였다는 것이다.
  • 부모 클래스인 Tv와 SmartTv로 예시를 들어보자.
class Tv{
	boolean power
    int channel;
    
    void power() {}
    void channelUp(){}
    void channelDown(){}
}

class SmartTv extends Tv{
	String text;            // 캡션(자막)을 보여주기 위한 문자열
    void caption(){}
}
  • 지금까지는 인스턴스 타입과 일치하는 타입의 참조변수만 사용했다.
    Tv t = new Tv(); SmartTv s = new SmartTv();
  • 서로 상속관계에 있을 경우, 부모클래스 타입의 참조변수로 자식 클래스의 인스턴스를 참조하도록 하는 것도 가능하다.
    Tv t = new SmartTv(); SmartTv s = new SmartTv(); 둘은 어떤 차이가 있을까.
  • SmartTv 인스턴스 2개를 생성하고, 참조변수 t와 s가 생성된 인스턴스를 하나씩 참조하도록 했다.
    인스턴스가 SmartTv타입이라 할지라도, 참조변수 t로는 SmartTv인스턴스의 모든 멤버를 사용할 수 없다. Tv타입의 참조변수로는 Tv클래스의 멤버들(상속받은 멤버 포함)만 사용할 수 있으며 따라서 Tv타입의 참조변수인 t는 SmartTv인스턴스의 멤버 중 Tv클래시에 정의되지 않은 멤버, textcaption()를 사용할 수 없다.
  • 둘 다 같은 타입의 인스턴이지만, 참조변수의 타입에 따라 사용할 수 있는 멤버의 개수가 달라진다.
  • 반대의 경우, 자식타입의 참조변수로 부모타입의 인스턴스를 참조하는 것은 불가능하다.

    부모타입의 참조변수로 자식타입의 인스턴스를 참조할 수 있다.
    바내로 자식타입의 참조변수로 부모타입의 인스턴스를 참조할 수는 없다.

참조변수의 형변환

  • 참조변수도 형변환이 가능하다.

  • 서로 상속관계에 있는 클래스 사이에서만 가능하기 때문에 자식타입의 참조변수를 부모타입의 참조변수로, 부모타입의 참조변수를 자식타입의 참조변수로의 형변환만 가능하다.

    바로 위 혹은 아래의 상속관계가 아니어도 가능하다. 부모의 부모로도 형변환이 가능한 것. 따라서 모든 참조변수는 모든 클래스의 조상인 Object클래스 타입으로 형변환이 가능하다.

  • 하지만 같은 부모를 상속하는 두 클래스가 형변환하는 것은 불가능하다.

  • Car 클래스와 FireEngine, Car와 Ambulance는 양방향 형변환이 가능하지만, FireEngine과 Ambulance는 형변환하는 것이 불가능하다.

  • 기본형의 그것과는 다르게, 참조형의 형변환은 변수에 저장된 값(주소값)이 변환되는 것이 아니다.
    참조변수의 형변환은 그저 리모컨(참조변수)을 다른 종류의 것으로 바꾸는 것일 뿐이고, 리모컨의 타입을 바꾸는 이유는 사용할 수 있는 멤버 개수를 조절하기 위한 것일 뿐이다.

  • 부모 타입으로의 형변환은 생략할 수 있는데, 부모타입으로 형변환하면 다룰 수 있는 멤버의 개수가 줄어들기 때문에 항상 안전하기 때문이다. 반면, 자식타입으로의 변환은 그렇지 않은데, 실제 객체가 가진 기능보다 멤버의 개수가 늘어나기 때문이다.

    서로 상속관계에 있는 타입간의 형변환은 양방향으로 자유롭게 수행될 수 있으나, 참조변수가 가리키는 인스턴스의 자손타입으로 형변환은 허용되지 않는다.
    그래서 참조변수가 가리키는 인스턴스의 타입이 무엇인지 먼저 확인하는 것이 중요하다.

instaceof 연산자

  • 참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 instanceof 연산자를 사용한다.
    주로 조건문에 사용되며, instatceof의 왼쪽에는 참조변수, 오른쪽에는 타입(클래스명)이 피연산자로 위치한다. 연산의 결과로는 boolean값인 true와 false중 하나를 반환한다.
  • instanceof를 이용한 연산결과로 true를 얻었다는 것은 참조변수가 검사한 타입으로 형변환이 가능하다는 것을 뜻한다.

    값이 null인 참조변수에 대해 instanceof 연산을 수행하면 false를 결과로 얻는다.

  • 부모타입의 참조변수로 자식타입의 인스턴스를 참조할 수 있기 때문에, 참조변수의 타입과 인스턴스이 타입이 항상 일치하지 않을수도 있다. 부모타입의 참조변수로는 실제 인스턴스의 멤버들을 모두 사용할 수 없기 때문에, 실제 인스턴스와 같은 타입의 참조변수로 형변환을 해야만 인스턴스의 모든 멤버들을 사용할 수 있다.

    어떤 타입에 대한 instanceof 연산의 결과가 true라는 것은
    검사한 타입으로 형변환이 가능하다는 것을 뜻한다.

0개의 댓글