Docsity
Docsity

Prepare for your exams
Prepare for your exams

Study with the several resources on Docsity


Earn points to download
Earn points to download

Earn points by helping other students or get them with a premium plan


Guidelines and tips
Guidelines and tips

Java Implementation of Common Data Structures using Object Class, Lecture notes of Algorithms and Programming

The implementation of common data structures in java using the object class. It covers the issues and solutions related to using object class for data structure implementation, including the use of equals and clone methods, and the need to define custom interfaces for listable data structures that require both clone and compareto methods.

Typology: Lecture notes

2017/2018

Uploaded on 10/23/2018

keehwan
keehwan 🇨🇦

20 documents

1 / 13

Toggle sidebar

This page cannot be seen from the preview

Don't miss anything!

bg1
- 37 -
제4장 자바를 이용한 범용 자료구조의 구현
장에서는 자바를 이용하여 범용 자료구조를 구현할 고려해야 하는 여러 가지 문제점
그것의 해결책을 살펴본다.
4.1. 교육목표
장의 교육목표는 다음과 같다.
교육목표
자바를 이용한 범용 자료구조의 구현
Object 클래스
equals 메소드
clone 메소드
Object 클래스를 이용한 범용 자료구조의 구현
compareTo 메소드
복사 방식 vs. 참조 방식
clone 메소드
Listable 인터페이스
4.2. 범용 자료구조
범용 자료구조 개요 (1)
범용 자료구조란 특정한 데이터 타입만 저장할 있는 구조가 아닌
모든 종류의 데이터를 저장할 있는 구조를 말한다.
3.1)
3.1) Point 데이터만 저장할 있는 PointList ADT는범
자료구조가 아니다.
범용 자료구조를 자바에서 구현하기 위해서는 다양한 종류의
데이터를 모두 저장할 있는 데이터 타입이 필요하다.
가장 쉽게 생각할 있는 것은 Object
Object 클래스
클래스이다.
Object 클래스는 자바에서 가장 최상위 조상 클래스이며,
명백하게 부모를 지정하지 않은 클래스의 부모는 항상 자동으로
Object 클래스가 된다.
객체는 그것의 조상 클래스 타입 변수에 대입할 있다.
따라서 모든 객체는 Object 타입의 변수에 저장할 있다.
범용 자료구조란 특정한 종류의 데이터만을 저장하기 위해 사용되는 구조가 아니라 다양한
종류의 데이터를 저장하기 위해 사용할 있는 자료구조를 말한다. 2장에서 살펴본
ArrayList 클래스는 자바 라이브러리에서 제공하는 범용 자료구조이지만 실습 3에서 구현한
pf3
pf4
pf5
pf8
pf9
pfa
pfd

Partial preview of the text

Download Java Implementation of Common Data Structures using Object Class and more Lecture notes Algorithms and Programming in PDF only on Docsity!

자바를 이용한 범용 자료구조의 구현 Object 클래스 equals 메소드 clone 메소드 Object 클래스를 이용한 범용 자료구조의 구현 compareTo 메소드 복사 방식 vs. 참조 방식 clone 메소드 Listable 인터페이스

범용 자료구조란 특정한 데이터 타입만 저장할 수 있는 구조가 아닌 모든 종류의 데이터를 저장할 수 있는 구조를 말한다. 예예 3.1)3.1) Point 데이터만 저장할 수 있는 PointList ADT 는 범용 자료구조가 아니다. 범용 자료구조를 자바에서 구현하기 위해서는 다양한 종류의 데이터를 모두 저장할 수 있는 데이터 타입이 필요하다. 이 때 가장 쉽게 생각할 수 있는 것은 ObjectObject 클래스클래스이다. Object 클래스는 자바에서 가장 최상위 조상 클래스이며 , 명백하게 부모를 지정하지 않은 클래스의 부모는 항상 자동으로 Object 클래스가 된다. 객체는 그것의 조상 클래스 타입 변수에 대입할 수 있다. 따라서 모든 객체는 Object 타입의 변수에 저장할 수 있다.

ArrayList 클래스는 자바 라이브러리에서 제공하는 범용 자료구조이지만 실습 3 에서 구현한

Point 데이터만 저장할 수 있는 PointList ADT는 범용 자료구조가 아니다. 범용 자료구조를 구현하기 위해서는 다양한 데이터 타입을 저장할 수 있는 방법이 필요하다. 자바에서 가장 쉽게 생각할 수 있는 것은 Object 클래스를 사용하는 것이다. 자바에서는 명백하게 부모 클 래스를 지정하지 않으면 Object 클래스가 부모 클래스가 된다. 따라서 Object 클래스는 자 바에서 가장 최상위 조상 클래스이다. 이 때문에 이 타입의 변수에는 어떤 타입의 객체도 저장할 수 있다.

Object 타입을 이용한 범용 자료구조 구현의 문제점 문제점문제점^ 1.1.^ 원시타입은^ Object^ 타입에 저장할 수 없다. 해결책해결책 .. Wrapper 클래스를 사용한다. 문제점문제점^ 2.2.^ 자료구조마다 그 자료구조에 저장되는 요소가 반드시 제공해야 하는 메소드가 있을 수 있다. 예예 3.2)3.2)^ 정렬리스트의 경우 저장되는 두 요소의 순위를 비교하는 메소드가 필요함. 예예 3.3)3.3) 자료구조를 만들 때 복사 방식 또는 참조 방식 두 가지 방식으로 사용하여 구현할 수 있다. 이 때 복사 방식을 사용하면 객체를 복제하는 메소드가 필요함 Object 타입을 사용할 경우에는 강제 타입 변환을 하지 않으면 이 클래스에 정의되어 있는 메소드만 호출할 수 있다. Object 타입에 필요한 메소드가 정의되어 있지 않을 수 있다.

자바에서 Object 타입을 이용하여 구현할 경우에는 몇 가지 문제점이 있다. 첫째, 원시타입 은 Object 타입의 변수에 저장할 수 없다. 즉, Object 타입 변수에 Rectangle, Student과 같 은 클래스 타입의 객체들은 저장할 수 있지만 int, double과 같은 원시타입은 저장할 수 없 다. 번거롭지만 이 문제점은 Wrapper 클래스를 이용하여 해결할 수 있다. 둘째, 자료구조마 다 그 자료구조에 저장되는 요소가 반드시 제공해야 하는 메소드가 있을 수 있다. 예를 들 어 정렬 리스트의 경우에는 저장되는 요소들이 정렬된 상태로 저장되어야 한다. 이를 위해 서는 두 요소의 순위를 비교하는 메소드가 필요하다. 그런데 자바에서는 한 타입의 변수를 통해서는 그 타입에 정의되어 있는 메소드만 호출할 수 있다. 즉, Object 타입의 변수이면 Object 클래스에 정의되어 잇는 메소드만 호출할 수 있다. 따라서 자료구조를 구현하기 위 해 Object 클래스에 정의되어 있지 않은 메소드가 필요하면 범용 자료구조를 만들기가 어렵 다. 이 장에서는 이런 상황을 어떻게 해결할 수 있는지 그 방법을 설명한다.

clone 메소드

Objectclone 메소드의 문제점 Object 클래스에 정의되어 있는 clone 메소드 : 이 메소드는 같은 타입의 객체를 자동으로 생성하고 인스턴스 필드의 값을 자동으로 복사한다. (shallow copy) 클래스의 멤버 변수 중 참조 타입이 있으면 문제가 발생할 수 있다. 예예 3.4)3.4) public class logbook{ private int logMonth;private int logYear; private int entry = new int[31]; … }

logMonth logYear entry

logMonth logYear entry

equals 메소드와 마찬가지로 Object의 clone 메소드는 재정의하여 사용하지 않으면 문제가 발생할 수 있다. Object의 clone 메소드는 같은 타입의 객체를 자동으로 생성하고 인스턴스 필드의 값을 기계적으로 복사하여 객체를 복제한다. 이런 복제를 shallow copy라 한다. 따라 서 클래스의 멤버변수 중 참조 타입이 있으면 복제한 후에 두 객체의 멤버변수가 동일한 것 을 참조하게 되는 문제점이 발생할 수 있다.

boolean equals(Object other)

equals 메소드의 구현 사전조건사전조건 :^ 비교하고자 하는 객체가^ null 이 아니어야 하며 , 같은 클래스의 인스턴스이어야 한다. 사후조건사후조건 :^ 객체의 내부 상태를 비교하여 내부 상태가 같은 경우에는 true 를 반환하고 , 그렇지 않으면 false 를 반환한다. 같은 클래스의 인스턴스인가를 검사하는 방법 instanceof 연산자 : 가능하지만 하위 클래스도 이 연산자를 이용한 검사에서 통과하므로 이 경우에는 사용할 수 없다. Object 클래스의 Class getClass() 메소드 사용 추가적 고려사항 동일 객체인지 검사한다. Æ if(this==other) return true; 인수의 타입이 Object 이므로 강제 타입 변환을 한 다음에 각 멤버변수를 비교해야 한다.

Object의 equals 메소드를 재정의할 때 고려해야 하는 사항은 다음과 같다. 첫째, 비교하고 자 하는 객체가 같은 클래스의 인스턴스이어야 한다. 보통 자바에서 객체가 어떤 특정 타입 인지 검사할 때에는 instanceof 연산자를 사용한다. 하지만 instanceof 연산자는 하위 클래스 도 이 검사에 통과하게 되므로 equals 메소드를 구현할 때에는 사용할 수 없다. 이를 위해 이 연산자 대신에 Class 클래스에 정의되어 있는 getClass 메소드를 사용한다. 둘째, 동일 객체가 메소드의 인자로 전달될 수 있다. 셋째, 인자의 타입이 Object이므로 받은 인자를 강 제 타입 변환한 후에 내부 멤버변수들의 상태를 비교해야 한다.

boolean equals(Object other) – 계속

예예 3.5)3.5) public class Date{private int year; private int month; private int day; …public boolean equals(Object other){ if(other==null||getClass() != other.getClass()) if(this == other) return true;return false; Date o = (Date)other; return year==o.year&&month==o.month&& day==o.day; } } …

public class MyDate extends Date{ private int val;… public boolean equals(Object other){ if(!super.equals(other)) return false;MyDate o = (MyDate)other; return val == o.val; } (^) 서브 클래스의 경우

Date라는 클래스에 대해 equals 메소드를 재정의하여 보자. 우선 비교하고자 하는 객체가 null이 아니어야 하며, 객체가 정확하게 Date 클래스의 인스턴스이어야 한다. 즉, Date의 하 위 클래스에 해당되는 객체와는 비교할 수 없다. 비교하고자 하는 객체가 null이 아니고 Date 클래스의 인스턴스이면 주어진 객체가 현재 객체와 같은 객체인지 먼저 검사한다. 이 런 검사가 끝나면 주어진 객체를 Date 객체로 변환한 다음에 Date의 각 멤버변수들의 값이 같은지 비교한다. 부모 클래스에 이미 equals 메소드가 정의되어 있는 경우에는 우선 부모 클래스의 equals 메소드를 호출하여 비교하고, 이 비교에 성공하면 현재 클래스에 추가로 정의되어 있는 멤버변수들의 상태를 비교한다.

Object clone()

Object 클래스의 clone 메소드는 객체의 멤버 변수 중에 참조 타입이 있으면 문제가 발생할 수 있다. 따라서 이 메소드는 protected 로 선언되어 있다., 재정의하지 않으면 호출할 수 없다. clone 을 재정의하는 경우에는 Cloneable 인터페이스를 구현한다. (^) public class Customer implements Cloneable{ private String name;private BankAccount account; …public Object clone(){ try{Customer cloned = (Customer)super.clone(); cloned.account = (BankAccount)account.clone();return cloned; }catch(CloneNotSupportedException e){ return null; } } }

멤버변수 중 참조 타입이있으면 그 변수마다 그 변수의 clone 을 호출한다.

앞서 언급한 바와 같이 Object의 clone 메소드는 shallow copy 방식의 복제를 하기 때문에 객체의 멤버 변수 중에 참조 타입이 있으면 심각한 문제를 초래할 수 있다. 이런 이유 때문 에 Object의 clone 메소드는 protected 멤버로 선언되어 있다. 따라서 하위 클래스에서 clone 메소드를 public 멤버로 재정의하지 않으면 객체 핸들을 이용하여 직접 호출할 수 없 다. clone을 재정의하는 경우에는 Cloneable 인터페이스를 구현한다고 표기하여, 이 사실을

4.4. Object 클래스를 이용한 범용 자료구조의 구현

Object 클래스를 이용한 범용 자료구조 요소들을 어떤 기준에 의해 정렬하지 않은 상태로 유지하는 자료구조의 경우에는 삽입은 비교적 쉽게 구현할 수 있으나 , 삭제는 내부적으로 요소들이 어떻게 저장되어 있는지와 무관하게 항상 삭제하고자 하는 요소가 현재 구조 내에 있는지 검사해야 한다. Object 클래스를 이용하여 범용 자료구조를 구현할 때에 내부 자료구조 뿐만 아니라 인자로 전달되는 객체를 받기 위해 Object 타입의 파라미터 변수를 사용한다. Object 클래스에 equals 메소드가 정의되어 있으므로 이 메소드를 이용하여 삭제하고자 하는 요소가 있는지 검사할 수 있다. 주의주의 .. Object 타입의 변수에 실제로 저장되어 있는 객체에 equals 메소드가 재정의되어 있지 않으면 우리가 원하는 효과를 얻을 수 없다.

대적으로 구현하기가 어렵다. Object 클래스를 이용하여 범용 자료구조를 구현하는 경우에 는 보통 내부 자료구조 뿐만 아니라 각 메소드에서 객체를 전달받아야 하는 경우에도 Object 타입의 파라미터 변수를 사용한다. Object 클래스에는 equals 메소드가 정의되어 있 으므로 이 메소드를 이용하여 찾고자하는 요소가 있는지 검사할 수 있다. 물론 이 때 Object 타입의 변수에 저장되어 있는 객체가 equals 메소드를 재정의하고 있지 않으면 우리 가 원하는 효과를 얻을 수 없다.

Object 클래스를 이용한 범용 자료구조 예예 3.6)3.6) public class UnsortedList{ Object[] list; int size = 0;public UnsortedList(int capacity){ list = new Object[capacity]; }public boolean delete(Object item){ for(int i=0; i<size; i++){ if(item.equals(list[i])){… } } }… }

자바의 late binding 기능 때문에 이 경우 Object 에 정의되어 있는 equals 참조하고 있는 객체에 정의되어 메소드가 아니라 item 이 있는 equals 메소드가 실행된다.

이 슬라이드의 예에서 delete 연산의 인자 타입은 Object이며, 내부적으로 이 인자의 equals 메소드를 호출하여 삭제하고자 하는 객체가 구조 내에 존재하는지 검사하고 있다. 그러나 실제 인자로 받게 되는 객체는 Object가 아닌 다른 타입일 것이다. 따라서 자바의 late

binding 특성 때문에 Object 클래스에 정의되어 있는 equals 메소드가 아니라 실제 item이 참조하는 객체에 정의되어 있는 equals 메소드가 호출된다.

Object 클래스를 이용한 범용 자료구조 요소들을 어떤 기준에 의해 정렬된 상태로 유지하는 자료 구조의 경우에는 삽입할 때 기존 요소들과 비교하여 삽입 위치를 결정해야 한다. 이런 비교는 자바에서는 보통 compareTo 메소드를 이용한다. Object 타입을 이용하여 범용 자료구조를 구현하고자 할 경우에는 Object 클래스에는 compareTo 메소드가 정의되어 있지 않으므로 예 3.6 처럼 쉽게 구현할 수 없다. Object 타입 변수에 저장되어 있는 객체에 compareTo 메소드가 정의되어 있어도 Object 타입 변수를 통해서는 compareTo 메소드를 호출할 수 없다. 강제 타입 변환을 하여 호출할 수 있지만 범용 자료구조 구현에서는 어떤 타입의 객체가 변수에 저장될지 모르기 때문에 가능하지 않다.

때 기존 요소들과 비교하여 삽입 위치를 결정해야 한다. 자바에서는 보통 compareTo 메소 드를 이용하여 이런 비교를 한다. 만약 Object 타입을 이용하여 이런 형태의 범용 자료구조 를 구현한다면 Object 클래스에는 compareTo 메소드가 정의되어 있지 않으므로 앞서 살펴 본 예 3.6과 달리 쉽게 구현할 수 없다. 강제 타입 변환하여 compareTo 메소드를 호출하는 방법을 생각해 볼 수 있지만 어떤 타입의 객체가 저장될지 알 수 없으므로 이것은 가능하지 않다.

Object 클래스를 이용한 범용 자료구조 예예 3.7)3.7) public class SortedList{ Object[] list;int size = 0; public SortedList(int capacity){ } list = new Object[capacity]; public void insert(Object item){ for(int i=0; i<size; i++){ int comp = item.compareTo(list[i]); // error… } }… }

public class Test{public static void main(String[] args){ SortedList list = new SortedList(10); list.insert(new Integer(10)); } }

이 예제에서 Integer 클래스는 compareTo 메소드가 정의되어 있지만전달된 객체의 타입과 상관없이 SortedListadd 메소드는 itemObject 타입이므로 item 을 이용하여 compareTo 를 호출할 수 없다.

이 슬라이드 예제처럼 실제 인자로 전달된 Integer 타입의 객체는 compareTo 메소드를 가 지고 있지만 insert 메소드 내에서 item은 Object 타입이므로 late binding과 상관없이 문범 적으로 compareTo 메소드를 호출할 수 없다.

구조에 유지하는 방식이다. 자바에서 객체의 복제는 보통 clone 메소드를 이용한다.

복사방식 vs. 참조방식

public void insert(Object item){ list[size] = item; size++; }

public void insert(Listable item){ list[size] = (Listable)item.clone(); size++; }

구현 예

위험성^ 외부에서 내부 내용을불법적으로 조작할 수 없다. 외부에서 내부 내용을불법적으로 조작할 수 있다. 속도 객체가 크고 복잡할수록 느리다. 일정하며 , 빠르다. 공간 두 배로 소요된다. 공간이 추가로 필요 없다.

복사방식 (by clone) 참조방식 (by reference)

여기서 Listableclone 메소드를 public 으로 선언하고 있는 인터페이스 타입이다.

class MyClass{ int value; Myclass(int n){ value=n; }public void set(int n){ value=n; } public int get(){ return value; } … } UnsortedList list = new UnsortedList(5);MyClass a1 = new MyClass(10); MyClass a2 = new MyClass(20); list.insert(a1);list.insert(a2); a1.set(5);

list

a1 a

105 20

이 슬라이드에 있는 예제에서 볼 수 있듯이 내부 상태가 10 과 20 인 객체를 list에서 삽입하 였지만 삽입할 때 사용된 a1를 이용하여 외부에서 a1의 값을 조작하면 list에 저장되어 있는 값도 변경된다. 하지만 복사 방식으로 구현되어 있는 경우에는 이런 위험은 없다.

clone

clonecompareTo 와 달리 Object 클래스에 존재한다. 하지만 Objectclone 메소드는 protected 멤버이므로 외부에서는 호출할 수 없다. Objectcloneshallow copy(cf. deep copy) 를 하기 때문에 객체의 멤버 중 참조 타입이 있으면 문제가 발생할 수 있다. 이 때문에 Objectclone 메소드는 protected 멤버로 정의되어 있다. 그러면 Cloneable 인터페이스를 이용하여 compareTo 문제를 해결한 것처럼 해결할 수 있을까? 가능하지 않다. Cloneable 인터페이스는 내용이 비어있는 marker interface 이다. 참고참고 .. marker interface 는 그것을 구현하는 클래스의 특성을 나타낸다. 어떤 메소드를 제공한다는 것을 나타내지 않는다. 예예 3.8)3.8) Serializable: 객체를 파일에 저장할 수 있음을 나타낸다.

clone의 문제점

예예 3.9)3.9)

해결책해결책 ..^ 새로운 인터페이스를 정의한다.

public class SortedList{ Object[] list; int size = 0; public SortedList(int capacity){list = new Object[capacity]; } public Object get(int index) {// return list[index].clone(); Cloneable x = (Cloneable)list[index]; } return x.clone(); // error; … }

Cloneable 인터페이스가 clone 메소드를 선언하고 있으면 이 메소드가 public 메소드가 되어 호출이 가능하지만 marker interface 이므로 가능하지 않다.

interface Copyable{ Object clone(); }

public void get(int index) {Copyable x = (Copyable)list[index]; return x.clone(); // ok; }

복사 방식으로 구현할 때에는 Object 타입을 이용하여 범용 자료구조를 만들기가 어렵다. Object 클래스는 clone 메소드를 제공하고 있으므로, equals 메소드의 예처럼 Object 타입을 사용하여 쉽게 구현할 수 있을 것으로 생각할 수 있다. 하지만 앞서 언급한 바와 같이 clone 메소드는 protected 멤버이므로 Object에 대한 핸들을 이용하여 clone 메소드를 호출 할 수 없다. 그러면 compareTo 메소드 문제를 해결한 것처럼 Cloneable 인터페이스를 이용 하여 해결할 수 있는가? 가능하지 않다. 그 이유는 Cloneable 인터페이스는 불행히도 marker 인터페이스이다. 일반적으로 인터페이스는 어떤 특정 메소드들을 제공한다는 것을 알려주기 위해 사용된다. 하지만 marker 인터페이스는 내용이 빈 인터페이스로서 그것을 구 현하는 클래스가 어떤 메소드들을 제공한다는 것을 나타내지 않고, 어떤 특성을 가진다는 것을 나타내기 위해 사용된다. 그러므로 실제 clone 메소드를 제공하는 객체들만 처리하기 위해서는 별도 인터페이스를 새롭게 정의하여 사용해야 한다.

Listable 인터페이스

Listable 인터페이스의 문제점 자바 라이브러리에서 제공하는 Integer 와 같은 기존 객체는 저장할 수 없다. 또한 기존 객체를 간단하게 Listable 제공하도록 다음과 같이 만들 수도 없다.

위 문제점에 대한 효율적인 해결책이 없음. 복사 방식의 구현을 포기하거나 , 아니면 저장할 객체마다 새롭게 Listable 을 구현하도록 새 클래스를 정의함.

class myInteger extends Integer implements Listable{public myInteger(int val){ super(val); } }

The type myInteger cannot subclassthe final class integer.

Listable 인터페이스를 새롭게 정의하여 사용하면 모든 문제가 부드럽게 해결되는 것은 아니 다. 자료구조에 저장하고자 하는 객체들이 Listable을 구현하고 있어야 한다. 우리가 새롭게 정의하는 데이터들이 Listable을 구현하도록 만드는 것은 어렵지 않지만 기존 객체들이 Listable을 구현하도록 만드는 것은 쉽지 않다. 특히 자바 라이브러리에서 제공되는 클래스 들은 보통 상속받을 수 없는 final 클래스이므로 이것이 매우 어렵다. 따라서 보통은 복사 방식으로 만드는 것을 포기한다.

Object 타입을 이용한 범용 자료구조에 대해 요약하면 다음과 같다. 범용 자료구조를 만들 기 위해서는 다양한 타입을 저장할 수 있는 타입이 필요하다. 자바에서는 Object 클래스가 가장 다양한 타입을 저장할 수 있으므로 보통 이 클래스를 사용하여 범용 자료구조를 구현 한다. 그런데 자료구조마다 그 자료구조에 저장되는 요소가 반드시 제공해야 하는 메소드가 있을 수 있다. 이와 관련하여 Object 타입을 이용할 때 크게 두 가지 경우로 나누어 생각해 볼 수 있다. 첫째, 필요한 메소드가 Object 클래스에 정의되어 있는 경우이다. 둘째, 필요한 메소드가 Object 클래스에 정의되어 있지 않은 경우이다. 전자의 경우 equals처럼 Object에 정의되어 있고, public 메소드이면 비교적 쉽게 구현할 수 있으며, 자료구조 자체보다는 자 료구조에 저장되는 요소들의 클래스를 만들 때 equals를 override하면 된다. 하지만 clone처 럼 정의되어 있어도 protected 메소드이면 이것을 호출할 수 있도록 인터페이스 기능을 이 용해야 한다. 후자의 경우에는 필요한 메소드를 선언되어 있는 인터페이스를 만들거나 이용 하여 해결할 수 있다.