자바의 정석 -(7장 객체지향 II - 2)

김우경·2022년 3월 13일
0
post-thumbnail

7장 2번째

가끔 헷갈리는 부분만 요약한 것입니다

4.5 접근 제어자

멤버 또는 클래스를 이부에서 접근하지 못하도로 제한하는 역할

private : 같은 클래스 내에서만
default : 같은 패키지 내에서만
protected : 같은 패키지내, 다른 패키지의 자손클래스
public : 제한 없음

객체지향 개념 캡슐화

  • 클래스나 멤버, 주로 멤버에 접근 제어자를 사용하는 이유는 클래스의 내부에 선언된 데이터를 보호하기 위해서이다.
  • 외부에는 불필요한, 내부적으로만 사용되는, 부분을 감추기 위해서

메서드 하나를 변경할 때 public 이라면 오류가 없는지 테스트 범위가 넓어지고, defalut라면 같은 패키지내에서만 확인, private라면 클래스내에서만 확인하면 된다. -> 상당한 차이

암묵적인 규칙
겟터(getter) : 보통 멤버변수의 값을 읽는 메서드이름
셋터(setter) : 멤버변수의 값을 변경하는 메서드이름

  • 하나의 소스파일(*.java)에는 public클래스가 단 하나만 존재할 수 있다.

생성자의 접근 제어자

생성자에 접근 제어자를 사용함으로써 인스턴스의 생성을 제한할 수 있다.
보통 생성자의 접근 제어자는 클래스의 접근 제어자와 같지만, 다르게 지정가능
ex

class Singleton{
private Singletion(){...}
}

외부에서 생성자에 접근할 수 없으므로 인스턴스를 생성할 수 없게된다.

대신 인스턴스를 생성해서 반환해주는 public메서드를 제공해서 외부에서 이 클래스의 인스턴스를 사용할 수 있도록 해야한다.

ex)

class Singleton{
private static Singleton e =new Singleton(); // 이처럼 미리 인스턴스가 생성되어있어야 한다.
private Singleton(){...}
//인스턴스를 생성하지 않고도 호출할 수 있어야 하므로
public static Singleton getInstance(){
return s; }
}
이처럼 생성자를 통해 직접 인스턴스를 생성하지 못하게 하고 public메서드를 통해 인스턴스에 접근하게 함으로써 사용할 수 있는 인스턴스의 개수를 제한

생성자가 private인 클래스는 다른 클래스의 조상이 될 수 없다.
자손클래스의 인스턴스를 생성할 때 조상클래스의 생성자를 호출이 불가능하기 때문이다.
그래서 클래스 앞에 final을 더 추가하여 상속할 수 없는 클래스라는 것을 알리는 것이 좋다.

정리

클래스 : public, default, final, abstract
메서드: 모든 접근 제어자, final, abstract, static
멤버변수 : 모든 접근 제어자, final, static
지역변수 : final

1. 메서드에 static과 abstract를 함께 사용할 수 없다.
static메서드는 몸통이 있는 메서드에만 사용할 수 있기 때문

2. 클래스에 abstract와 final을 동시에 사용할 수 없다.
클래스에 사용되는 final은 확장할 수 없다는 의미, abstract 는 상속을 통해 완성

3. abstract메서드의 접근 제어자가 private일 수 없다.
자손클래스에서 구현해주어야 하는데 접근 불가

4.메서드에 private과 final을 같이 사용할 필요는 없다.
접근 제어가자 private인 메서드는 오버라이딩될 수 없기 때문이다.

5.다형성

객체지향개념의 중요한 특징 중 하나 다형성
객체지향개념에서 다형성이란 '여러 가지 형태를 가질 수 있는 능력'을 의미한다.
한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 한다.
즉 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 한다.

ex)

class Tv{
boolean power;
void power()
void channelUp()
}

class CaptionTv exetends Tv{
String text;
void caption()
}

두 클래스가 서로 상속관계에 있을 때 조상 클래스 타입의 참조변수로 자손 클래스의 인스턴스를
참조하도록 하는 것도 가능하다.
원래 > Tv t = new Tv(), CaptionTv c = new CaptionTv()
-> Tv t = new CaptionTv(); //조상 타입의 참조변수로 자손 인스턴스를 참조

하지만 반대로 자손타입의 참조변수로 조상타입의 인스턴스 참조하는 것은 안된다.
참조변수가 사용할 수 있는 멤버의 개수는 인스턴스의 멤버 개수보다 같거나 적어야한다.
클래스는 상속을 통해서 확장될 수는 있어도 축소될 수는 없다.

  • 참조변수의 타입이 참조변수가 참조하고 있는 인스턴스에서 사용할 수 있는 멤버의 개수를 결정한다는 사실이 중요

    조상타입의 참조변수로 자손타입의 인스턴스 참조 가능
    자손타입의 참조변수로 조상타입의 인스턴스 참조 불가

5.2 참조변수의 형변환

기본형 변수와 같이 참조변수도 형변환이 가능하다.
단, 서로 상속관계에 있는 클래스사이에서만 가능하다.
자손타입 -> 조상타입 : 형변환 생략가능
자손타입 <- 조상타입 : 형변환 생략불가
ex)

class Car(){..}
class Fire extends Car(){...}

Car car =null;
Fire f = new Fire();
Fire fe = null;
car = fe; 형변환 생략가능 업캐스팅
fe = (Fire)car; 형변환 생략불가 다운캐스팅

  • 형변환은 참조변수의 타입을 변환하는 것이지 인스턴스를 변환하는 것은 아니기 때문에 참조변수의 형변환은 인스턴스에 아무런 영향을 미치지 않는다.
    단지 참조변수의 형변환을 통해서 참조하고 있는 인스턴스에서 사용할 수 있는 멤버의 범위(개수)를 조절하는 것뿐이다.

  • 컴파일 시에는 참조변수간의 타입만 체크하기 때문에 생성될 인스턴스의 타입에 대해서는 전혀 알지못해 참조에러는 발생하지않는다(컴파일시!)

상속관계에 있는 타입간의 형변환은 자유롭지만 참조변수가 가리키는 인스턴스의 자손타입으로 형변환은 혀용되지 않는다.
그래서 참조변수가 가리키는 인스턴스의 타입이 무엇인지 확인하는 것이 중요하다.

5.3 instanceof연산자

참조변수가 참조하고 있는 인스턴스의 실제 타입을 알아보기 위해 사용
ex) if (c tnstanceof FireEngine)
instanceof의 왼쪽에는 참조변수를 오른쪽에는 타입(클래스명)

5.4 참조변수와 인스턴스의 연결

  • 조상 타입의 참조변수와 자손 타입의 참조변수의 차이점중 하나는 사용할 수 있는 멤버의 개수에 있다고 배웠다.

  • 한 가지 더, 조상 클래스에 선언된 멤버변수와 같은 이름의 인스턴스변수를 자손 클래스에 !!중복!!으로 정의했을 때, 조상타입의 참조변수로 자손 인스턴스를 참조하는 경우와 자손타입의 참조변수로 자손 인스턴스를 참조하는 경우는 서로 다른 결과를 얻는다.

  • 메서드의 경우 자손 클래스가 오버라이딩한 경우에도 참조 변수의 타입에 관계없이 항상 실제 인스턴스의 메서드(오버라이딩된 메서드)가 호출되지만, 멤버변수의 경우 참조변수의 타입에 따라 달라진다.

ex)
Parent p = new Child()
Child c = new Child()

class Parent(
int x = 100;
)
class Child extends Parent(
int x = 200;
)

class BindingTest3{
public static void main(String[] args) {
Parent5 p = new Child5();
Child5 c = new Child5();

System.out.println("p.x = " + p.x);
p.method();
System.out.println();
System.out.println("c.x = " + c.x);
c.method();
#nbsp }
}
class Parent5 {
int x = 100;

void method() {
System.out.println("Parent Method");
}
}
class Child5 extends Parent5 {
int x = 200;
void method() {
System.out.println("x=" + x); // this.x와 같다.
System.out.println("super.x=" + super.x);
System.out.println("this.x=" + this.x);
}
}

  • 상속받은 인스턴스변수 구분을 위해 참조변수 super, this를 사용
    주로 private 으로 접근을 제한하고 외부에서는 메서드를 통해서만 멤버변수에 접근할 수 있도록 하지, 참조변수를 통해 직접적으로 인스턴스변수에 접근할 수 있게 하지 않는다.

5.5 매객변수의 다형성

조상타입의 참조변수를 매개변수로 사용

5.6 여러 종류의 객체를 배열로 다루기

조상타입의 참조변수 배열사용 -> 공통의 조상을 가진 서로 다른 종류의 객체를 배열로 묶어서 다룰 수 있다.
Product p[] = new Product[3];
p[0] = new Tv();
p[1] = new Computer();
p[2] = new Audio();

위 경우에는 배열 크기가 3이 제한적이다. 무조건 배열의 크기를 크게 할 수 없기 때문에
Vector클래스 : 내부적으로 Object타입의 배열을 가지고 있어서, 이 배열에 객체를 추가하거나 제거할 수 있게 작성되어 있다. 알아서 배열의 크기를 관리해준다.
단지 동적으로 크기가 관리되는 객체배열

메서드/생성자
Vector()

boolean add(Object o) : Vector에 객체 추가 성공:true 실패:false

boolean remove(Object o) : Vector에 저장되어 있는 개체를 제거 성공:true 실패:false

boolean isEmpty() : Vector가 비어있는지 검사 true,false

Object get(int index) : 지정된 위치(index)의 객체를 반환, 반환타입이 Object타입이므로 적절한 타입으로의 형변환 필요

int size() : Vector에 저장된 객체의 개수 반환

0개의 댓글