(생명 코딩) 액세스 컨트롤러, 추상, 최종, 인터페이스, 다형성



1. 액세스 제어

자유와 규제

너무 자유롭다면 소통이 어려워지므로 적절한 규제가 필요하다.

규정에는 액세스 수정자, 추상 클래스, 최종 및 인터페이스가 포함됩니다.

문법

액세스 수정자

개체에서 멤버(변수, 메서드)를 사용할 때의 권한

// public이 접근 제어자
public String x(){
    return "public";
}

// private이 접근 제어자
private String y(){
    return "private";
}

사용 이유

보안이나 논리상의 이유로 사용자 즉, 외부로부터의 접근을 규제함으로써 오작동 발생을 줄일 수 있기 때문이다.

미세 제어

공공의 보호 기본 사적인
같은 패키지
같은 반
영형 영형 영형 영형
같은 패키지
상속 관계
영형 영형 영형 엑스
같은 패키지
상속 X
영형 영형 영형 엑스
다른 패키지
계승
영형 영형 엑스 엑스
다른 패키지
상속 X
영형 엑스 엑스 엑스

기본적으로 공개 및 비공개를 알고 있으므로 나중에 보호 및 기본을 사용할 수 있습니다.

  • 같은 클래스의 경우 접근 수식어와 상관없이 사용 가능
  • 동일한 패키지 내에서 private만 사용할 수 없습니다.
  • 다른 패키지의 경우 public만 가능하지만 다른 패키지의 하위 클래스가 상속되면 보호도 가능합니다.
  • public은 어디에서나 접근 가능, private는 같은 클래스 내에서만 사용 가능

클래스 액세스 한정자

  • 기본값은 액세스 한정자가 첨부되지 않은 경우이며 동일한 패키지에서만 사용할 수 있습니다.
  • public은 다른 패키지의 클래스에서 사용할 수 있습니다.

공개 클래스 이름과 파일 이름이 동일해야 합니다.

PublicNameDemo.java

package org.opentutorials.javatutorials.accessmodifier.inner;
//public class PublicName {} <ㅡ 에러 발생
public class PublicNameDemo {}

하나의 소스 코드에는 하나의 공용 클래스만 존재할 수 있기 때문입니다.


2. 초록

문법

추상은 한국어로 ‘추상’을 의미합니다.

추상 클래스를 사용하려면 상속해야 합니다. 규제한다고 볼 수 있습니다.

abstract class A{
    public abstract int b();
    public void d(){
        System.out.println("world");
    }
}

// 추상 클래스 A를 오버라이딩
class B extends A{
    public int b(){return 1;}
}

public class AbstractDemo {
    public static void main(String() args) {
        // A obj = new A(); <ㅡ 에러 발생
        B obj = new B();
        System.out.println(obj.b());
    }
}
  • 추상 메서드에는 본문이 없어야 합니다. 즉, 중괄호 안에 내용이 없어야 합니다.
  • 멤버 중 하나라도 추상이면 클래스는 추상입니다.

사용 이유

공통 부분은 추상 클래스를 사용하여 대략적으로 정의됩니다.

상황에 따라 변경되는 유연한 부분은 사용할 때마다 변경할 수 있도록 하는 것입니다.

// ex)
abstract class robot{
    public void attack(){}
}

class punchRobot extends robot{
    public void attack(){
        System.out.print("punch");
    } 
}

class missileRobot entends robot{
    public void attack(){
        System.out.print("missile");
    }
}

디자인 패턴

추상화를 사용하여 템플릿을 결정한 후 하위 클래스에 책임을 위임하는 패턴입니다. 템플릿 메서드 패턴그것은 말한다.

이 반복되는 패턴은 디자인 패턴오전.

장점

  • 좋은 디자인은 단기간에 배울 수 있습니다.
  • 의사소통에 도움이 됩니다.


3. 최종

상속 또는 변경 금지 규정

첫 번째 정의 이후에는 변경할 수 없습니다.

// final 필드: 값 변경 불가
static final double PI = 3.14;

// final 메소드: 상속 불가
class A{
    final void a(){}
}

// final 클래스: 상속 불가
final class b{
    final void b(){}
}


4. 인터페이스

문법과 개념

인터페이스를 사용하는 개체는 인터페이스의 메서드를 구현해야 합니다.

interface I{
    public void z();
}
 
class A implements I{
    public void z(){}
}

위의 코드에서 클래스 A는 인터페이스 I을 “구현”합니다.

사용 이유

인터페이스는 클래스에 대한 사양 역할을 합니다.

인터페이스를 사용하는 클래스는 사양을 지정하여 사용할 수 있습니다.

// 인터페이스
public interface Calculatable {
    public void setOprands(int first, int second, int third) ;
    public int sum(); 
    public int avg();
}

// 인터페이스를 구현한 클래스
class CalculatorDummy implements Calculatable{
    public void setOprands(int first, int second, int third){
    }
    public int sum(){
        return 60;
    }
    public int avg(){
        return 20;
    }
}

메인 클래스
public class CalculatorConsumer {
    public static void main(String() args) {
        CalculatorDummy c = new CalculatorDummy();
        c.setOprands(10, 20, 30);
        System.out.println(c.sum()+c.avg());
    }
}

규칙

하나의 클래스는 여러 인터페이스를 구현할 수 있습니다.

interface I1{
    public void x();
}
 
interface I2{
    public void z();
}
 
class A implements I1, I2{
    public void x(){}
    public void z(){}   
}

인터페이스도 상속됩니다.

interface I3{
    public void x();
}
 
interface I4 extends I3{
    public void z();
}
 
class B implements I4{
    public void x(){}
    public void z(){}   
}

인터페이스의 멤버는 public이어야 합니다.

인터페이스를 사용하는 다른 클래스가 액세스할 수 있도록 공용이어야 합니다.

추상 VS 인터페이스

  • 추상 클래스는 일반 클래스이므로 구체적인 논리 또는 상태를 가질 수 있습니다.
  • 인터페이스는 구체적인 논리나 상태를 가질 수 없습니다.


5. 다형성

메소드 오버로딩과 다형성

다형성

하나의 메서드나 클래스가 있으면 서로 다른 방식으로 작동합니다.

예) 과부하

클래스와 다형성

class A{
    public String x(){return "x";}
}

class B extends A{
    public String y(){return "y";}
}

public class PolymorphismDemo1 {
    public static void main(String() args) {
        A obj = new B();
        obj.x(); 
        obj.y(); // 에러 발생
    }
}

위 코드는 obj 인스턴스의 타입인 A 클래스의 y 메소드가 존재하지 않기 때문에 에러가 발생합니다.

메서드 x가 자식 클래스인 B 클래스에 오버로드되어도 오류가 발생하지 않습니다.

  • 부모 타입으로 자식 인스턴스가 생성되고 자식 메서드가 부모 메서드를 오버로드하면 자식 메서드가 더 높은 우선 순위를 갖습니다.
  • 타입이 부모이므로 자식 클래스에만 존재하는 메서드는 사용할 수 없습니다.

인터페이스와 다형성

public class CalculatorDemo {
    public static void execute(Calculator cal){
        System.out.println("실행결과");
        cal.run();
    }
    public static void main(String() args) { 
        Calculator c1 = new CalculatorDecoPlus();
        c1.setOprands(10, 20);
         
        Calculator c2 = new CalculatorDecoMinus();
        c2.setOprands(10, 20);
         
        execute(c1);
        execute(c2);
    }
}
  • c1과 c2는 데이터 유형이 같지만 인스턴스가 다르기 때문에 기능이 다릅니다.
  • 인스턴스와 동일한 데이터 타입으로 생성할 경우 각 타입별로 execute 메소드를 생성해야 하므로 코드 중복이 발생한다.

interface I2{
    public String A();
}

interface I3{
    public String B();
}

class D implements I2, I3{
    public String A(){
        return "A";
    }
    public String B(){
        return "B";
    }
}

public class PolymorphismDemo3 {
    public static void main(String() args) {
        D obj = new D();
        I2 objI2 = new D();
        I3 objI3 = new D();
         
        obj.A();
        obj.B();
         
        objI2.A();
        //objI2.B();
         
        //objI3.A();
        objI3.B();
    }
}
  • 클래스가 인터페이스를 구현하는 경우 클래스 유형은 구현 인터페이스 유형이 될 수 있습니다.
  • objI2의 타입이 인터페이스 I이므로 I에 대한 메소드가 존재하지 않아 오류가 발생한다. ojbI3.A()의 오류 발생 원인도 이와 같다.