콘텐츠로 이동

클래스와 객체

클래스는 값과 그 값을 다루는 동작을 함께 표현합니다. 객체를 생성하고 메서드를 호출한 뒤 상태를 읽는 순서로 살펴봅니다. 각 코드에서 필드·생성자·호출 대상을 찾고, 빌드·실행 버튼으로 현재 서버의 실제 결과를 확인할 수 있습니다. 실행 지원 한계는 현재 실행 확인 범위에 정리되어 있습니다.

Counter의 value는 객체가 보관하는 필드입니다. 생성자는 클래스와 이름이 같고 반환 타입을 쓰지 않습니다. Counter(10)으로 만들 때 전달한 초기값을 this.value에 저장합니다. 객체 생성에 new를 붙이지 않습니다.

class Counter {
    int value;

    public Counter(int initial) {
        this.value = initial;
    }

    public void add(int step) {
        this.value = this.value + step;
    }

    public int current() {
        return this.value;
    }
}

class CounterExample {
    static void main() {
        Counter first = Counter(10);
        Counter second = Counter(0);
        first.add(2);
        print(first.current());
        print(second.current());
    }
}

다른 언어의 탭은 직접 작성한 대응 코드이며 컴파일러의 자동 생성 결과가 아닙니다. 언어마다 API와 실행 환경이 다릅니다. 이 페이지의 빌드·실행은 Unibase 탭에서 사용할 수 있습니다.

서버 실행을 준비 중입니다.
출력 비교 기준
12
0
Unibase 소스 내려받기

검증 상태: 문법 검사 통과 · 실행 출력 일치 (2026-10-06)

읽기 기준 결과와 실제 실행 출력 비교

코드를 읽어 정한 비교 기준입니다. 실행 성공 결과로 대신 표시하지 않습니다.

12
0

실제 네이티브 실행: 빌드 passed, 실행 passed, 종료 코드 0

12
0
현재 실행 확인 범위

first.add(2)는 첫 객체의 값을 바꾸는 호출입니다. 코드 읽기 기준으로 첫 객체는 12, 두 번째 객체는 0을 보관합니다. 객체마다 필드가 따로 보관되는지 두 결과를 함께 확인해야 합니다.

this는 현재 객체입니다. 다른 클래스에서 사용하는 생성자와 메서드는 public으로 선언합니다. static 메서드는 객체를 만들지 않고 클래스 수준에서 호출할 때 사용합니다.

생성자는 객체를 처음 사용할 수 있는 상태로 만드는 곳입니다. Counter(10)은 초기값을 받는 계약이므로 인수를 생략하거나 문자열을 전달하는 호출과 다릅니다. 클래스 이름과 같은 생성자 이름, 매개변수의 개수·타입, 접근 범위를 함께 확인합니다.

Counter.value를 감추고 add()와 current()를 제공하면 값의 변경 경로가 분명해집니다. 모든 필드를 public으로 공개하면 다른 코드가 상태를 직접 바꿀 수 있습니다. 값을 조회하는 메서드와 변경하는 메서드를 분리하면 어느 호출이 상태를 바꾸는지 읽기 쉽습니다.

호출 형태 사용하는 상태
first.add(2) first라는 특정 객체의 상태
second.current() second의 별도 상태
static int square(int value) 객체 없이 입력값을 사용하는 클래스 수준 계산

static 문맥에서 객체 없이 인스턴스 필드를 참조하는 코드는 현재 의미 검사에서 거절됩니다. 객체 상태가 필요하면 그 객체를 전달하거나 객체의 메서드로 호출하세요.

Worker extends Named는 이름 필드와 조회 메서드를 부모 클래스에서 가져오고, 자식 클래스에 index를 추가하는 구조입니다.

class Named {
    public string name;

    public string getName() {
        return this.name;
    }
}

class Worker extends Named {
    public int index;

    public Worker(string name, int index) {
        this.name = name;
        this.index = index;
    }
}

class InheritanceExample {
    static void main() {
        Worker worker = Worker("worker", 3);
        print(worker.getName());
        print(worker.index);
    }
}

다른 언어의 탭은 직접 작성한 대응 코드이며 컴파일러의 자동 생성 결과가 아닙니다. 언어마다 API와 실행 환경이 다릅니다. 이 페이지의 빌드·실행은 Unibase 탭에서 사용할 수 있습니다.

서버 실행을 준비 중입니다.
출력 비교 기준
worker
3
Unibase 소스 내려받기

검증 상태: 문법 검사 통과 · 실행 출력 일치 (2026-10-06)

읽기 기준 결과와 실제 실행 출력 비교

코드를 읽어 정한 비교 기준입니다. 실행 성공 결과로 대신 표시하지 않습니다.

worker
3

실제 네이티브 실행: 빌드 passed, 실행 passed, 종료 코드 0

worker
3
현재 실행 확인 범위

worker.getName()은 부모에 선언한 메서드를, worker.index는 자식에 추가한 필드를 사용합니다. 상속은 두 클래스가 같은 기본 속성과 동작을 공유할 때 고려할 수 있습니다. 재정의와 동적 호출의 실행 지원을 이 예제로 확정하지 않습니다.

인터페이스는 구현할 메서드의 이름·매개변수·반환 타입을 선언합니다. Transform은 정수를 받아 정수를 반환하는 apply()를 요구하고, DoubleValue가 본문을 작성합니다.

interface Transform {
    int apply(int value);
}

class DoubleValue implements Transform {
    public int apply(int value) {
        return value * 2;
    }
}

class InterfaceExample {
    static void main() {
        DoubleValue transform = DoubleValue();
        int result = transform.apply(7);
        print(result);
    }
}

다른 언어의 탭은 직접 작성한 대응 코드이며 컴파일러의 자동 생성 결과가 아닙니다. 언어마다 API와 실행 환경이 다릅니다. 이 페이지의 빌드·실행은 Unibase 탭에서 사용할 수 있습니다.

서버 실행을 준비 중입니다.
출력 비교 기준
14
Unibase 소스 내려받기

검증 상태: 문법 검사 통과 · 실행 출력 일치 (2026-10-06)

읽기 기준 결과와 실제 실행 출력 비교

코드를 읽어 정한 비교 기준입니다. 실행 성공 결과로 대신 표시하지 않습니다.

14

실제 네이티브 실행: 빌드 passed, 실행 passed, 종료 코드 0

14
현재 실행 확인 범위

이 코드는 구현 클래스에서 apply(7)을 호출하는 구조입니다. 현재 확인한 컴파일러는 구현 객체를 인터페이스 타입 변수에 대입하는 소스를 거절하므로, 인터페이스 참조를 통한 다형성 예제로 확대하지 않습니다. Thread와 비동기 작업에서도 Runnable.run()과 Callable.call()의 구현을 사용합니다.

인터페이스를 구현할 때는 이름만 같은 메서드를 만드는 것이 아니라 매개변수·반환 타입과 공개 접근을 계약에 맞춰 작성합니다. void apply(int)는 int apply(int)의 구현이 아닙니다. 여러 구현을 교체해 사용하는 동적 호출은 구현 클래스의 직접 호출과 따로 검증해야 합니다.

객체를 필드로 보관하면 필요한 동작을 그 객체에 맡길 수 있습니다. Calculation은 Multiplier를 전달받고, run()에서 곱셈을 위임합니다.

class Multiplier {
    int factor;

    public Multiplier(int factor) {
        this.factor = factor;
    }

    public int apply(int value) {
        return value * this.factor;
    }
}

class Calculation {
    Multiplier multiplier;

    public Calculation(Multiplier multiplier) {
        this.multiplier = multiplier;
    }

    public int run(int value) {
        return this.multiplier.apply(value);
    }
}

class CompositionExample {
    static void main() {
        Calculation calculation = Calculation(Multiplier(2));
        print(calculation.run(4));
    }
}

다른 언어의 탭은 직접 작성한 대응 코드이며 컴파일러의 자동 생성 결과가 아닙니다. 언어마다 API와 실행 환경이 다릅니다. 이 페이지의 빌드·실행은 Unibase 탭에서 사용할 수 있습니다.

서버 실행을 준비 중입니다.
출력 비교 기준
8
Unibase 소스 내려받기

검증 상태: 문법 검사 통과 · 실행 출력 일치 (2026-10-06)

읽기 기준 결과와 실제 실행 출력 비교

코드를 읽어 정한 비교 기준입니다. 실행 성공 결과로 대신 표시하지 않습니다.

8

실제 네이티브 실행: 빌드 passed, 실행 passed, 종료 코드 0

8
현재 실행 확인 범위

호출 흐름은 calculation.run(4) → multiplier.apply(4) → 4 * 2입니다. Multiplier(3)을 전달하면 같은 호출 구조에서 배수를 바꿀 수 있습니다. 상속 대신 객체 관계로 동작을 구성하는 방식입니다.

관계 이 장의 코드 사용을 고려할 상황
상속 Worker extends Named 같은 기본 속성·동작을 확장
인터페이스 구현 DoubleValue implements Transform 구현할 메서드 계약을 표현
객체 조합 Calculation이 Multiplier 보관 필요한 동작을 다른 객체에 위임

이름이 비슷하다는 이유만으로 상속 관계를 만들기보다, 호출자가 어떤 계약을 필요로 하는지 먼저 확인하세요. 변경할 동작을 생성자로 전달하는 조합은 그 관계를 소스에 드러냅니다.