본문 바로가기

Programming Languages [PL]

[PL] 11. Support for Object-Oriented Programming

Object-Oriented Programming 언어의 주요 특징

Abstraction 추상화

implementation을 숨김 - Readability가 올라간다. 재사용성이 올라감 + 모듈화(유지보수 쉬워짐)

 

Encapsulation 캡슐화

Member와 접근하는 Method를 합침, Member에 접근하려면 Method를 통해서만 가능 - 보안성이 높아짐

 

Re-use 재사용

Inheritance(상속)를 통해서 가능 - 모듈별로 재사용 가능하게 한다.

 

Polymorphism 다형성

Dynamic Function(Method) Binding - 정의된 함수가 실행될 때 run-time에 어떤 객체인지 보고 결정


Inheritance (상속)

Re-use로부터 생산성을 향상할 수 있다.

상속이 없는 ADT는 재사용이 어렵다. 항상 수정해야 한다.

상속이 없는 ADT는 독립적이며 항상 같은 레벨에 위치한다.

상속은 새 클래스를 기존의 클래스를 기반으로 정의하는 것을 가능하게 한다. (공통된 부분을 상속함으로써)

상속은 적은 변경 후에 ADT를 재사용함으로써 클래스를 계층적으로 정의할 수 있게 한다.


Object-Oriented Concepts

ADT는 일반적으로 Class라고 부른다.

Class InstanceObject라고 부른다.

상속받는 Class는 ‘Derived Class’ 혹은 ‘Subclass’이다.

다른 Class가 상속하는 Class는 ‘Parent Class’ 혹은 ‘Superclass’이다.

Object(객체)에 대한 동작을 정의하는 Subprogram을 ‘Method’라고 부른다.

Method를 호출하는 것을 ‘Message’라고 부른다.

객체의 전체 Method 모음을 ‘Message Protocol’ 혹은 ‘Message Interface’라고 부른다.

Message는 2가지 파트가 있다. -> a method name + the destination object (메소드 이름 + 대상 객체)

 

상속은 entity를 캡슐화하기 위한 access control로 인해 복잡해질 수 있다.

  • 클래스는 그것의 Subclass로부터 entity를 숨길 수 있다.
  • 클래스는 그것의 Client로부터 entity를 숨길 수 있다.
  • 클래스는 Subclass가 entity를 보는 것을 허용하면서 동시에 Client에게는 숨길 수 있다.

Method를 그대로 상속받는 것 외에도 클래스는 상속받은 method를 수정할 수 있다.

  • 새로운 Method가 상속받은 것을 Override한다.
  • 부모 클래스의 Method는 Override된다.

부모 클래스와 클래스가 달라질 수 있는 3가지 방법

  1. Subclass는 부모로부터 상속받은 variable이나 method에 variable이나 method를 추가할 수 있다.
  2. Subclass는 상속받은 Method 중 하나 혹은 그 이상을 수정할 수 있다.
  3. 부모 클래스는 subclass에서 보이지 않도록 private access를 가지게 variable과 method를 정의할 수 있다.

Class의 Variable 두 가지

  • Class variables : 클래스 하나마다 가지는 변수 (모든 객체가 공유하는 변수) (C++, Java의 Static, Python은 def 밖에)
  • Instance variables : 객체 하나마다 가지는 변수

Class의 Method 두 가지

  • Class method : 클래스 자체 종속되는 method - accept messages to the class
    (method 정의할 때, C++, Java는 Static, Python은 def 위에 @)
  • Instance method : instance 하나하나마다 다르게 동작하는 method - accept messages to objects

단일 상속 vs 다중 상속 (Single vs Multiple Inheritance)

  • Java는 다중 상속이 안 된다. (Interface를 사용한다.)

재사용을 위한 상속의 한 가지 단점

  • 유지보수를 복잡하게 만드는 클래스 간의 종속성(interdependency)를 생성한다.

Dynamic Binding (dynamic method binding)

polymorphic variable(다형성 변수)는 클래스의 객체 또는 그 클래스의 하위 클래스의 객체를 참조할 수 있다.

클래스 다형성이 method를 override하는 클래스를 포함하고 그 method들이 다형성 변수를 통해 호출된다면, dynamic하게 binding하는 것이 올바른 방법이다.

Dynamic binding은 소프트웨어 시스템을 개발 및 유지보수 과정에서 더 쉽게 확장할 수 있게 해준다.

Abstract method : 정의를 포함하지 않는 method. (protocol만 정의한다.) - 상속받아서 override하는 것이 목적

Abstract class : 최소한 하나의 virtual method(가상 메소드)를 포함하는 클래스 / instant화될 수 없다.

상속을 위해서 만드는 클래스


Design Issues for OOP Languages


OPP in C++

일반적인 특징

  • C와 SIMULA 67에서부터 발전했다.
  • 널리 사용된 첫 객체 지향 언어이다.
  • 혼합된 typing system : C와의 역호환성을 위해 C의 type system을 보존하고 Class를 추가했다.
  • C++의 객체는 Static / Stack-dynamic / Heap-dynamic 이 가능
  • C++은 암묵적으로 저장소 회수를 지원하지 않기 때문에 heap-dynamic 객체에 대한 Delete 연산이 필요
  • C++의 클래스는 Data member와 Member function을 가질 수 있다.
  • 다른 OOP 언어에서 Member function은 주로 method라고 부른다. 

상속

stand-alone class : C++만 가능, Java/Python은 기본적으로 Object의 상속을 받는다.

C++의 클래스는 상속 없이 독립적으로 존재할 수도 있고 존재하는 클래스로부터 파생될 수도 있다.

 

C++의 멤버 Access control

  • Private - 같은 클래스 혹은 Friend만 볼 수 있다. Subclass가 subtype이 되는 것을 허락하지 않음
  • Public - Subclass와 client 모두 볼 수 있음
  • Protected - Subclass만 볼 수 있음, Client는 볼 수 없음

Subclassing 과정은 access control과 함께 선언될 수 있다.

  • Private derivation : 상속된 public과 protected 멤버들은 서브 클래스에서 private이다.
  • Public derivation : 상속된 public과 protected 멤버들은 서브 클래스에서 동일하게 public과 protected이다. 

Reexportation 재수출
클래스는 보여야만 하는 멤버를 제공하기 때문에 그 멤버들은 public으로 정의된다. 파생된 클래스는 새로운 멤버를 
추가하고 부모 클래스에서 public으로 정의되었지만 client가 부모 클래스의 멤버를 보지 못하게 하고 싶을 때 서브 클래스에서 접근할 수 없는 멤버는 ‘::’라는 범위 지정 연산자를 사용해 보이도록 선언할 수 있다.

 

다중 상속의 지원

두 상속된 멤버가 같은 이름을 가지고 있다면, 범위 지정 연산자 :: 를 사용하여 둘 다 참조할 수 있다. 


Dynamic Binding

method는 virtual(가상)로 정의될 수 있다.

다형성 변수를 통해 호출되고 message에 동적으로 바인딩될 수 있다.

pure virtual function은 아무런 정의가 없는 함수이다. (body가 없다.)

하나 이상의 pure virtual function을 가지는 클래스는 추상 클래스(Abstract Class)이다.

C++에서 프로그래머는 design time에 method가 정적/동적으로 binding될지 정해야만 한다.

Static이 빠르다.


OPP in Java

일반적인 특징

  • procedural programming(절차적 프로그래밍)은 지원하지 않음 (다 객체이기 때문에)
  • 부모가 없는 클래스는 없다.
  • primitive type을 제외한 모든 데이터는 객체이다.
  • 모든 primitive type은 하나의 데이터 값을 저장하는 wrapper class를 가진다. (int는 Integer 등)
  • 모든 객체는 heap-dynamic이고 참조 변수를 통해 참조되며 대부분 new를 사용하여 할당된다.
  • finalize method는 객체에 의해 차지된 저장 공간을 garbage collector가 회수하기 전에 암묵적으로 호출된다.

상속

  • 단일 상속만 지원한다.
  • 다중 상속의 장점을 제공하는 추상 클래스 범주의 ‘interface’가 있다.
  • 인터페이스는 오직 method 선언과 named constants만 포함할 수 있다.
  • 인터페이스는 member는 X, method만 있을 수 있다. 상속도 안 된다.
  • method는 final로 선언될 수 있다. (override될 수 없다.)
  • 모든 subclass는 subtype이다. 

Dynamic Binding

모든 message는 method에 동적으로 바인딩된다.

method가 final인 경우 override될 수 없기 때문에 dynamic binding은 의미가 없다.

Static binding은 method가 static 혹은 private일 때 사용된다. 둘 다 override를 허용하지 않는다.


Dynamic Binding of Method Calls

정적으로 바인딩된 클래스의 method는 Class instance records(CIR)에 포함될 필요가 없다.

동적으로 바인딩된 method는 CIR에 entry를 가지고 있어야 한다.

동적으로 바인딩된 method의 호출은 CIR의 포인터를 통해서 해당하는 코드에 연결될 수 있다.

저장 구조는 때로 virtual method tables (vtable)이라고 불린다

Method call(호출)은 vtable의 시작으로부터의 offset으로 표현될 수 있다. -> 속도가 느리다. (indirect)


Reflection

reflection을 지원하는 프로그래밍언어는 프로그램이 타입과 구조에 대해 runtime access를 가질 수 있도록 허용

또한 동적으로 그들의 행동을 수정할 수 있도록 허용

 

프로그램의 타입과 구조는 metadata라고 불린다. -> reflection은 metadata를 쫓아갈 수 있게 만들어준 함수를 묶어둔 것

 

reflection은 Java와 C# 등 대부분 동적으로 타입을 지정하는 언어에서 사용할 수 있다.

 

소프트웨어 도구에서 reflection의 사용

  • Visual IDEs는 개발자가 올바른 타입의 코드를 작성하도록 type information을 사용한다.
  • 디버거는 private field와 클래스의 method를 검사한다.
  • 테스트 시스템은 클래스의 모든 method를 알아야 한다.

단점

  • 비용이 많이 든다. 속도가 느려진다.
  • private field와 method를 노출한다.
  • 초기 type checking의 이점이 사라진다.
  • 몇몇 reflection 코드는 보안 관리자 아래에서 실행이 되지 않을 수 있다. (코드의 이식성이 사라진다.)