본문 바로가기

Development/JAVA

(Java) Chapter11. 접근 제어자

1. 자유와 규제

  1) 배경

    규제 중의 하나는 데이터 타입이 있다. 어떤 변수가 있을 때 그 변수에 어떤 데이터 타입이 들어있는지, 또 어떤 메소드가 어떤 데이터 타입의 데이터를 리턴하는지를 명시함으로써 사용하는 입장에서는 안심하고 변수와 메소드를 사용할 수 있게 된다. 이러한 규제에는 추상 클래스, final, 접근제어자, 인터페이스 등이 포함된다. 

  2) 접근 제어자의 개념

    접근제어자는 클래스의 맴버(변수와 메소드)들의 접근 권한을 지정한다.

  3) 접근 제어자 사용 이유

    사용자가 객체 내부적으로 사용하는 변수나 메소드에 접근해서 발생하는 의도하지 못한 오류를 막기 위해 사용함

 

2. 클래스 맴버에 대한 접근 제어자

  1) Public (어떠한 조건에서도 접근 가능)

  2) Private (같은 클래스를 제외한 패키지, 다른 패키지의 서브클래스에서는 접근 불가)

class Calculator8{
    private int left, right;       // private 은 class 에서는 사용 가능하지만 외부에서는 사용 불가

    public void setOprands(int left, int right) {
        this.left = left;
        this.right = right;
    }
    private int _sum() {
        return this.left + this.right;
    }
    public void sumDecoPlus() {
        System.out.println("++++" + _sum() + "++++");
    }
    public void sumDecoMinus() {
        System.out.println("----" + _sum() + "----");
    }
}

public class _02_Private2 {
    public static void main(String[] args) {
        Calculator8 c1 = new Calculator8();
        c1.setOprands(10, 20);
        c1.sumDecoPlus();
        c1.sumDecoMinus();
        // c1.left = 100; 이라고 할 때 현재 전역변수는 프라이빗으로 제한되어있기 때문에 오류가 발생함
        // 즉, public 만 사용자가 접근 가능하다.
        // private 은 같은 클래스에서만 사용 가능하다.
    }
}

  3) protected (같은 클래스, 패키지에서는 접근 가능, 다른 패키지라고 하더라도 상속관계라면 접근 가능, 관계 없는 클래스에서는 접근 불가)

 

  4) default (같은 클래스, 패키지에서는 접근 가능, 다른 패키지면 상속관계라고 하더라도 접근 불가, 관계없는 클래스에서는 접근 불가)

 

  ※ 제한 정도 : public < protected < default < private

  같은 클래스 같은 패키지 다른 패키지 하위 클래스 관계 없음
public O O O O
protected O O O X
default O O X X
private O X X X

 

3. 클래스 접근 제어자

  1) public (다른 패키지의 클래스에서도 사용 가능, public 접근 제어자 선언)

 

  2) default (같은 패키지에서만 사용 가능, 접근제어자를 붙이지 않으면 default, import로 불러와도 사용 불가능)

 

4. abstract

  1) 개념

    상속을 강제하는 규제으로 추상 클래스나 메소드를 사용하기 위해서는 반드시 상속해서 사용하도록 강제하는 것

  2) 추상 메소드

package chapter_10;
abstract class A1 {
    public abstract int b();
        // 본체가 있는 메소드는 abstract 키워드를 가질 수 없다.(아래와 비교)
        // public abstract int c() { System.out.println("Hello");}
        // 추상 클래스 내에는 추상 메소드가 아닌 메소드가 존재할 수 있다.
    public void d() {
        System.out.println("world");
    }
}
class B extends A1 {                 // 2. 추상 메소드를 사용하기 위해 상속
    public int b() {                // 3. 추상 클래스에 본체가 없어 오버라이딩
        return 1;
    }
}
public class _03_Abstract {
    public static void main(String[] args) {
        // A obj = new A();        // 1. 추상메소드이므로 인스턴스 생성 불가
        B obj = new B();           // 4. 상속된 하위 클래스 인스턴스 생성
    }
}

  3) 추상 클래스 사용 이유

  - 상위 클래스에는 메소드의 시그니처에만 정의해놓고 그 메소드의 실제 동작 방법은 이 메소드를 상속받은 하위 클래스의 책임으로 위임.

  - 공통적인 부분은 클래스에, 용도에 따라 달라지는 구현을 사용자가 직접 하도록 할 때

package chapter_10;
abstract class Calculator9 {
    int left, right;
    public void setOprands(int left, int right) {
        this.left = left;
        this.right = right;
    }
    int _sum() {                        // default 접근 제어자
        return  this.left + this.right;
    }
    public abstract void sum();
    public abstract void avg();
    public void run() {                 // 구체적인 동작 방법은 하위 클래스에 존재
        sum();
        avg();
    }
}
class CalculatorDecoPlus extends Calculator9 {  // 직접 구현해야 할 부분 1
    public void sum() {
        System.out.println("+ sum : " + _sum());
    }
    public void avg() {
        System.out.println("+ avg : " + (this.left + this.right) / 2);
    }
}
class CalcualtorDecoMinus extends Calculator9 {  // 직접 구현해야 할 부분 2
    public void sum() {
        System.out.println("- sum : " + _sum());
    }
    public void avg() {
        System.out.println("- avg : " + (this.left + this.right) / 2);
    }
}
public class _04_AbstractClass {
    public static void main(String[] args) {
        CalculatorDecoPlus c1 = new CalculatorDecoPlus();
        c1.setOprands(10, 20);
        c1.run();                       // + sum : 30   / + avg : 15

        CalcualtorDecoMinus c2 = new CalcualtorDecoMinus();
        c2.setOprands(10, 20);
        c2.run();                       // - sum : 30   / - avg : 15
    }
}

  4) 디자인 패턴

  - template pattern이라고도 함

  - 공통적으로 반복되는 패턴들을 이름을 부여해서 정리해둔 것

  - 만들면서 찾아볼 것.

 

5. final

  - 한번 값이 정해진 이후 변수 내의 값이 고정할 때 사용하는 규제

package chapter_10;

final class Calculator {                    // final class (아래 1)에 영향)
    static final double PI = 3.14;          // final 메소드 (아래 2) 영향)
    int left, right;
    
    public void setOprands(int left, int right) {
        this.left = left;
        this.right = right;
        Calculator.PI = 6;                  // 2) 고정되어있기 때문에 에러발생
    }
    final void b() {}                       // final 메소드 (아래 3)에 영향)
}

class CalculatorPlus extends Calculator {   // 1) 클래스가 고정되어있으므로 상속도 불가
    void b() {}                             // 3) 상위 클래스에서 고정되어 오버라이딩 불가
}

public class _05_Final {
}

 

6. Interface

  1) 개념

    객체가 있고 그 객체가 특정 인터페이스를 사용한다면 그 객체는 반드시 인터페이스의 메소드들을 구현하도록 강제됨

package chapter_10;
interface I {               // 인터페이스 정의
    public void z();
}

class A2 implements I {      // '클래스 A는 인터페이스 I를 구현한다.'
    public void z() {}      // 인터페이스 구동 방식 정의
}

  2) 실질적인 쓰임

예를 들어, 클래스 개발과 사용자 단 개발이 동시에 이루어질 때, 둘 중 하나의 코드를 맞게 변경을 해야한다고 하는 경우, 인터페이스를 사용하여 통합하고 양측을 인터페이스를 구현하는 코드로 수정(예시가 약간 억지스러워 이해만 하고 넘어감. 요약하면, 클래스가 인자 2개로 만들었고 사용자단은 인자가 3개가 될 것으로 만들었을 때 3개를 기준으로 인터페이스로 규약하고 구현하는 코드로 수정)

 

  3) 인터페이스의 규칙

  - 인터페이스의 메소드는 반드시 public이어야 구현 가능

  - 하나의 클래스는 복수의 인터페이스를 구현 가능

interface I1 {               // 인터페이스 정의
    public void z();
}
interface I2 {
    public void x();
}

class A2 implements I1, I2 {      // '클래스 A는 인터페이스 I를 구현한다.'
    public void z() {}      // 인터페이스 구동 방식 정의
    public void x() {}
}

  - 인터페이스도 상속 가능

interface I3{
    public void x();
}
interface I4 extends I3 {   // 인터페이스 상속
    public void z();
}
class B implements I4{      // 상속된 인터페이스를 포함한 하위 인터페이스 정의
    public void x() {}
    public void z() {}
}

 

  - abstract vs. interface

    추상 클래스는 일반적인 클래스. 인터페이스는 구체적인 로직이나 상태를 가지고 있을 수 없고, 추상 클래스는 구체적인 로직이나 상태를 가지고 있을 수 있음

 

7. 다형성

  1) 개념

  - 하나의 메소드나 클래스가 있을 때 이것들이 다양한 방법으로 동작하는 것을 의미

  - 예를 들어 키보드를 누른다 라는 조작방법은 같지만 키에 따라 실행의 목적이 다름

  - 오버로딩을 생각하면 매개변수가 다른 오버로딩 된 메소드가 있을 때 이를 메소드의 다형성이라고 볼 수 있음

  - 즉, 상속관계에 있을 때 나타나는 다양한 형질들을 일컬음

  2) 클래스와 다형성

class A2{
    public String x() {return "A.x";}
}
class B2 extends A2 {
    public String x() {return "B.x";}       // A2 상속
    public String y() {return "y";}         // A2를 B2인스턴스화 하면 A2에 존재하지않으므로 없는 것으로 여겨짐
}
class B3 extends A2 {
    public String x() {return "B3.x";}      // A2 상속에 다른 하위 클래스
}
public class _08_Polymorphism {
    public static void main(String[] args) {
        A2 obj = new B2();                  // 상위 클래스인 척 하는 하위클래스이므로 상위의 메소드는 없는 것으로 여겨짐
        A2 obj2 = new B3();                 // 위와 마찬가지
        System.out.println(obj.x());        // B2.x
        System.out.println(obj2.x());       // B3.x
    }
}

  3) 메소드와 다형성

  - 하나의 추상 클래스에 두 개의 메소드가 있고 하위 클래스 두 개가 상위의 두 메소드를 정의한다고 한다면, 메인영역에서 이를 하나로 통합하면 두 메소드의 인스턴스를 각각 생성하더라도 변수는 공통의 추상클래스만으로 정의가 가능함

  - 이때 하나로 통합할 때 사용하는 키워드는 'execute'

 

  4) 인터페이스와 다형성

  - 두 개의 인터페이스가 있고 두개의 강제하는 클래스가 있을 때, 생성된 인스턴스는 각각 강제적으로 정의된 클래스가 연결된 인터페이스만을 불러올 수 있으며 나머지 인터페이스는 사용하지 않도록 제한함

 

'Development > JAVA' 카테고리의 다른 글

(Java) Chapter13. Object  (0) 2023.01.23
(Java) Chapter12. 예외  (0) 2023.01.23
(Java) Chapter10. API  (0) 2023.01.10
(Java) Chapter8. 생성자와 상속  (0) 2023.01.10
(Java) Chapter7. 객체 지향 프로그래밍  (0) 2023.01.08