카테고리 없음

Lecture 11: Object-Oriented Languages

용학사 2024. 12. 6. 16:39

11-1)객체지향 언어

Simula-67

실세계에 있는 객체들을 표현하고 이들 사이의 상호작용을 시뮬레이션하기 위한 언어로 개발

 

Smalltalk

최초로 GUI 제공

 

C++

초기에는 C에 클래스 개념만 도입된 것이였지만 다양한 기능이 추가되면서 점차 향상되었다.

 

Java

언어의 단순성과 플랫폼 독립성이 장점이다.객체지향 패러다임에 충실하게 고안되었기 때문에 C++보다 오용의 소지가 적다.

 

Objective-C/Swift

C와 객체지향 언어를 혼합한 언어 C++보다는 Smalltalk에 좀 더 가깝게 정의된 언어

 

C#

마이크로소프트에서 개발한 객체지향 프로그래밍 언어 문법적인 특성이 Java와 유사하다.

 

Python

플랫폼에 독립적이며 동적 타이핑을 지원하는 대화형 인터프리터 언어이면서 객체지향 개념을 포함한 다중 패러다임 언어이다.

 

객체지향 언어의 주요 개념

객체지향 프로그래밍은 왜 시작되었을까?

->실세계에 있는 객체들을 표현하고 이들 사이의 상호작용을 시뮬레이션하기 위해서

 

객체지향 프로그래밍(Objct-Oriented Programming, OOP)은 프로그램을 여러 개의 독립된 단위, 즉 "객체" 들의 모음으로 파악하고 각각의 객체는 메시지를 주고받고, 데이터를 처리할 수 있는 개체이다.

 

실세계의 객체를 프로그램 상에 어떻게 표현할 수 있을까?

객체는 그 객체의 속성(attribute)과 그 객체의 행동(behavior)으로 이루어진다.

11-2)Java 클래스

클래스 정의

예제1
/* 계좌를 나타내는 클래스를 정의한다. */
class Account
{
	private String name;
    private long balance;
    
    Account(String name){
		this.name = name;
        balace = 0;
    }
    
   	public long getBalace(){
    	return balace;
    }
    
    public long deposit(long amount) {
    	balance += amount;
        return balance;
    }
    
    public long withdraw(long amount) {
    	if(amount <= balace)
        	balance -= amount;
        else System.err.println("잔액 부족");
        return balace;
    }
 }

 

생성자(constructor)는 클래스아 같은 이름을 갖는 특수한 메소드로 new 연산자에 의해 객체가 생성될 때 자동으로 실행된다.  생성자는 리턴 값이 없어서 리턴 타입이 없으며 생성자에 리턴 타입을 사용하면 컴파일 오류이다.

필요하면 오버라이딩이 가능하다.

 

객체 생성

객체 참조 변수(object reference variable)로 객체를 가리키기 위한 변수이다.

클래스이름 변수;

객체 참조 변수를 선언해도 객체 생성된 건 아니다.

객체를 생성하기 위해서는 new 연산자를 사용해야 한다.

new 연산자는 객체를 하나 생성하고 그 객체에 대한 참조 주소를 리턴한다.

변수 = new 클래스이름();

 

11-3) 캡슐화

추상 자료형(abstract data type)은 데이터(자료구조)와 관련된 연산(프로시저)들을 한데 묶어 캡슐화하여 정의한 자료형이다.

 

클래스도 추상 자료형의 발전된 형태라고 할 수 있다

 

왜 캡슐화(encapsulation)가 필요할까?

객체의 내부 구현 세부 사항을 캡슐화한다.

외부로부터의 잘못된 사용으로부터 손상되지 않도록 한다.

 

객체의 외부에서 보면 내부의 세부사항들은 보이지 않고 객체가 제공하는 서비스 즉 프로그램의 다른 부분과의 소통하는 방법들만 보인다.

 

서비스를 제공하는 메소드들은 그 객체의 창구(interface)역할을 한다 

 

캡슐화된 객체는 마치 블랙박스처럼 내부의 일은 다른 객체들로부터 감추어져있다.

 

접근 제어자(access modifier)

public: 공용 접근 제어자

프로그램 내의 어느 곳에서나 접근 가능

 

potected:보호 접근 제어자

 

private: 전용 접근 제어

클래스 내부에서만 접근 가능

 

11-4) 정적 변수 및 정적 메소드

클래스로부터 실체 즉 객체를 생성하면 각 실체 변수들은 독립적으로 별도의 기억공간에 값을 유지한다. 따라서 한 클래스의 여러 객체들은 실체 변수를 공유해서 사용할 수 없다. 

/*  Account 객체의 개수를 위해 실체 변수 counter 사용*/
class Account
{
	int counter = 0;
    
    public Account() {
	
    public Account() {
    	counter++;
    }
    ...
}

변수 counter를 실체 변수로 선언하면 객체가 이를 위한 별도의 기억공간을 갖게된다. 따라서 객체가 생성될 때마다 이 변수 값을 증가하여도 값은 언제나 1이다.

 

Static

stati 변수는 객체가 아니라 클래스 내에 변수를 위한 기억공간이 생성되므로 정적변수(static variable) 혹은 클래스 변수(class variable)라고 한다.

 

정적 메소드(static method)

객체를 생성하지 않고도  클래스 이름을 이용하여 호출하는것이 가능하며 이 떄문에 실체 변수는 사용할 수 없다. 

 

/* Account 객체의 개수를 위해 정적 변수 counter 사용*/
class Account
{
	static int counter = 0;
    
    public Account() {
		counter++;
    }
    
    public static int getCounter() {
		return counter;
    }
    
    public static void main(String[] args) {
		Account acc1 = new Account();  //counter = 1 
        Account acc2 = new Account();  //counter = 2
        System.out.println(Account.counter); //counter = 2
        System.out.println(Account.getCounter());//counter = 2
    }
}

 

 

11-5) 제네릭

제네릭 프로그래밍

-매개변수 다형성

      제네릭 클래스로 작성할 수 있는 기능은 타입 매개변수에 따라 여러 타입에 적용되어 사용될 수 있기 때문에

       매개변수 다형성(parametric polymorphism)이라고 한다.

 

-java 1.5부터 추가되었으며 주로 java Collection에서 많이 사용된다.

 

제네릭 클래스(generic class)

-타입을 매개변수로 받아 여러 타입에 적용될 수 있도록 포괄적으로 정의된 클래스를 재네릭 클래스라고 한다.

-매개변수 다형성

      제네릭 클래스로 작성할 수 있는 기능은 타입 매개변수에 따라 여러 타입에 적용되어 사용될 수 있기 때문에

       매개변수 다형성(parametric polymorphism)이라고 한다.

 

예제4
import java.util.ArrayList;
import java.util.Iterator;
class Drawable { void paint(){} } 
class Circle extends Drawable { } 
class Rectangle extends Drawable { }
 
 
public class Collectionl {
 	public static void main(String args[]) {
 		ArrayList myList = new ArrayList();
 		myList.add(new Circle());
 		myList.add(new Rectangle());
 		myList.add(new Integer(l));
 
 		for (Iterator i = myList.iterator(); i.hasNext(); ) { 
	 	  Drawable obj = (Drawable) i.next(); 
		  obj.paint();
 		} 
	} 
}
//이 예에서는 for 
루프 내에서 i.next()를 사용하여 저장된 객체를 가져오면 타입 변환을 통해 Drawable 
객체인지 확인한다. 이 예제처럼 myList가 Drawable 타입의 객체가 아닌 Integer와 같은 
다른 객체를 포함하면, 이 타입 변환은 실패하고 예외가 발생할 것이다.

 

예제5
public class Collection2 {
	public static void main(String args[]) {
    	ArrayList<Drawable> myList = new ArrayList<Drawable>();
        myList.add(new Circle());
        myList.add(new Rectangle());
        //myList.add(new Integer(1)); 오류
        
        for (Drawable obj: myList)
        	obj.paint();
     }
}      
//세 번째 줄에 
서 제네릭을 사용하여 컬렉션에 저장되는 객체의 타입을 Drawable 객체로 미리 한정할 수 
있다. 그러면 myList에 Drawable이 아닌 객체를 추가하는 시도는 모두 컴파일 오류를 발 
생한다. 따라서 myList에서 값을 검색할 때도 명시적인 타입 변환은 더 이상 필요 없다

 

제네릭 클래스 정의

 

public class 클래스명<T> {...}

클래스를 설계할 때 타입 매개변수를 사용하여 정의, 구체적인 타입을 지정하면 컴파일러가 클래스를재구성해준다.

 

 

제네릭 메소드

타입 매개변수를 이용하여 여러 타입에 적용하여 사용할 수 있도록 포괄적으로 정의한 메소드를 제네릭 메소드(generic method)라고 한다.

public class TestBox {
	public static <T> Box<T> boxing(T t) {
		Box<T> box = new Box<T>();
		box.set(t); 
		return box;
 	}
 	public static void main(String[] args) {
 		Box<String> boxl = TestBox.<String>boxing("test ");
 		Box<Integer> box2 = TestBox.<Integer>boxing(100);
 		System.out.printIn(boxl.get() + box2.get());
 	}
 }
 
 실행결과
 test 100
 
 //이 제네릭 메소드를 두 번 호출하여 Box<String>와 Box<Integer>를 각각 생성하여 사용한다

 

11-6)Python클래스

클래스 정의

class 클래스명:
	def __init__(self, 매개변수):
    	...
    
    def 매소드명(self, 매개변수):	
        ...

- __init__메소드는 생성자(constructor)라고 하는 메소드로 객체가 생성된 후 자동으로 호출된다.

  주로 객체(객체의 속성을 나타내기 위한 실체 변수들(instance variable)를 초기화하고 리턴 값이 없다

 

- Python에서는 변수를 선언하지 않고 사용한다. 따라서 객체의 실체 변수도 별도로 선언하지 않고 사용한다.

 

-self는 Java의 this처럼 자신 객체를 나타내며 "self.변수이름"은 객체의 실체 변수를 나타냄

 

객체 변수와 클래스 변수

객체 변수(objcer variable)

-각 객체마다 이 변수를 위한 기억공간이 별도로 존재하는 필드 변수로 Java의 실체 변수(instance variable)에 해당

 

클래스 변수(class variable)

-클래스에 하나 존재하여 그 클래스의 모든 객체가 공유하는 변수로 Java의 정적 변수(static variable)에 해당한다.

 

접근 제어

 

예제 10
class Account:
	def __init__(self, name):
    	self.__name = name
        self.__balance = 0
   	
    def getBalace(self):
    	return self.__balace
    
    def deposit(self, amount):
    	self.__balance += amount
        return self.__balace
    ...

>>> my = Account('kim')
>>> my.__balance

결과
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 AttributeError: 'Account' object has no attribute '__balance'
 
 >>> my.desposit(300000)
 >>> my.getBalance()
 300000

다음과 같이 테스 트해 보면 해당 변수는 외부에서 접근할 수 없음을 알 수 있다(정확히는 해당 변수가 없는 것처럼 오류 메시지가 나온다). 또한 이 변수를 deposit, getBalance와 같은 공용 메소드 를사용하여 접근할 수 있다

 

11-7)C++ 클래스

-new 연산자를 이용해 객체를 동적으로 생성

 

-new T: T 타입의 객체를 생성하고 새로 생성된 객체에 대한 포인터를 반환

 

-delete p: p가 가리키는 객체를 제거한다.

 

Account *p =new Account() ;

(*p).deposit()

p->deposit()

 

C++템플릿

템플릿은 C++프로그래밍 언어의 제네릭 프로그래밍 기능으로 함수나 클래스를 Java의 제네릭처럼 포괄적으로 동작할 수 있도록 작성해준다.

예제12

template <typename T>
T sum(T a, T b){
	return a+b;
}

뿐만 아니라 클래스 템플릿은 클래스를 타입 매개변수를 사용하여 여러 타입에 포괄적으로 적용될 수 있도록 작성할 수 있다.

tmeplate <typenmae 변수이름>
class 클래스이름{
	//클래스 정의
}