객체(Object)
- 객체 : 데이터, 작업을 모두 캡슐화하는 컨테이너
- ADT 변수 : 해당 데이터만 나타낸다.
- 변수 자체를 사용하여 작업을 호출
- void increment(Counter c)
- 객체의 데이터 항목 : 인스턴스 변수(instance variables)
- 작업 : 메서드(method)
메소드 호출(Method Invocation)
- 객체에 대한 작업 실행은 객체에 메시지를 전송하여 수행
- object.method(params)
- 객체에 대한 메소드 호출
- 객체에게 메소드를 호출하도록 지시
- 객체 자체는 메소드의 암시적 매개변수로 간주될 수 있다.
클래스(Class)
- 클래스 : 객체 집합의 모델
- 클래스가 있는 언어에서는 모든 객체가 클래스에 속한다.
- 객체는 클래스의 인스턴스로 간주될 수 있다.
- 객체는 해당 클래스의 인스턴스화에 의해 동적으로 생성된다.
- 예) Counter c = new Counter();
클래스와 객체
- 메소드는 클래스에 한 번만 저장된다.
- 각 개체(인스턴스)에는 자체 인스턴스 변수가 포함되어 있다.
- 클래스의 메소드에 대한 포인터도 객체에 저장된다.
- 자체 참조의 경우 메서드에서는 this(또는 self)를 사용
캡슐화(Encapsulation)
- public, private
- 숨겨야 할 정보 : private
- 일반적으로 데이터와 일부 메소드 : private
- 인터페이스 역할을 하는 메소드 : public
- 캡슐화(Encapsulation): 클래스라는 캡슐로 데이터와 작업을 함께 래핑
- 정보 숨기기(Information hiding) : 캡슐 내부의 세부 정보를 비공개 영역에 배치하여 숨기는 것
하위 타입(Subtypes)
- S 인터페이스가 T 인터페이스의 하위 집합인 경우 T는 S의 하위 타입
- 타입 S의 값이 필요한 곳에 타입 T의 값을 넣어도 아무 문제가 없다면 T는 S의 하위타입이다.
- S의 모든 작업은 T에서 가능
- T는 S의 모든 필드뿐만 아니라 추가 필드를 가질 수도 있다.
class NewCounter extends Counter{ private int num_reset = 0; public int get_reset() { return this.num_reset; } } |
생성자(Constructor)
- 객체 생성
- 메모리 할당
- 개체 데이터의 초기화
- 후자는 생성자(Constructors)로 수행
- 클래스와 동일한 이름을 사용하거나 다른 고유한 이름을 사용하는 경우가 많다.
C++, Java class Counter{ public Counter() { ... } } |
Python class Counter: def __init__(self): ... |
- 생성자 선택(Constructor Selection)
- 클래스에 두 개 이상의 생성자(오버로딩)
- 어느 것을 사용?
- C++의 복사 생성자
- 생성자 체이닝(Constructor Chaining)
- 슈퍼클래스의 일부는 어떻게/언제 초기화?
- 어떤 슈퍼클래스 생성자를 어떤 인수로 호출?
상속(Inheritance)
- 상속 : 기존 개체의 재사용을 기반으로 새 개체(또는 클래스)를 정의
- 상속 vs. 하위 타입
- 상속 : 코드 재사용(reuse, 구현 상속) 가능성
- 하위 타입 : 호환성(compatibility, 인터페이스 상속)
- 하위 클래스에 대한 보호 키워드
- 단일, 다중 상속
- 하나의 슈퍼클래스를 허용, 아니면 여러 개의 슈퍼클래스를 허용?
- 다중 상속으로 인해 문제 발생
- 이름 충돌
- 다이아몬드 문제
다이아몬드 문제
- 어느 f()를 불러야 할지 모르겠다.
- 한정된 이름으로 메서드를 명시적으로 지정합니다.
동적 메소드 조회
- Counter 예시
- Counter 및 NewCounter는 클래스에 정의되어 있다.
- Counter를 재설정하려고 하면 어떻게 할까?
Counter arr[100]; ... arr[9] = new Counter(); arr[10] = new NewCounter(); ... for(int i=0; i<100; i++){ arr[i].reset(); } class Counter{ private int x = 0; public void reset() { x = 0; } public void inc() { x += 1; } public int get() { return x; } } class NewCounter extends Counter{ private int num_reset = 0; public void reset() { x = 0; num_reset += 1; } public int get_reset() { return this.num_reset; } } |
- 컴파일러는 메소드가 호출될 객체의 유형이 무엇인지 결정할 수 없다.
- 클래스 A에서 f는 g를 호출. 이는 보다 명시적으로 this.g()
- 따라서 실제 g는 이 지점이 어떤 객체인지에 따라 나중에 실행에서 사용할 수 있다.
- this, self의 후기 바인딩(late binding)
class A { int a = 0; void f() { g(); } void g() { a = 1; } } class B extends A{ int b = 0; void g() { b = 2; } } B b = new B(); b.f(); |
메소드 오버라이딩(Overriding) 및 섀도잉(Shadowing)
- 메소드 오버라이딩(Overriding) : 하위 타입에서 메소드를 재정의
- 섀도잉(Shadowing) : 하위 타입에서 필드를 재정의
- 단, 참고하는 경우에는 차이가 있다.
- 오버라이딩 : 동적(dynamic)
- 섀도잉 : 정적(static)
public class A { public int num = 5; public int update() { return num-1; } } public class B extends A { public int num = 3; public int update() { return num+5; } B b = new B(); A a = b; System.out.println(b.num); //3 System.out.println(b.update()); //8 System.out.println(a. num); //5 System.out.println(a.update()); //8 |
'프로그래밍언어론' 카테고리의 다른 글
[프로그래밍언어론] 30. 데이터 추상(Data Abstraction) (0) | 2023.11.06 |
---|---|
[프로그래밍언어론] 29. 스크립팅 언어(Scripting Languages) (0) | 2023.11.06 |
[프로그래밍언어론] 28. 프로그래밍 언어 패러다임(PL Paradigm) (0) | 2023.11.06 |
[프로그래밍언어론] 27. 자료형(Data Types) (1) | 2023.10.17 |
[프로그래밍언어론] 26. 바인딩 정책(Binding Policy) (1) | 2023.10.17 |