윤 홍 란 hryun@sookmyung.ac.kr 4 장 클래스 작성 윤 홍 란 hryun@sookmyung.ac.kr
클래스 작성 지금까지는 java 클래스 라이브러리에 미리 정의된 클래스들을 사용하였다. 이 장에서는 사용자가 정의하는 클래스를 작성하는 방법을 배운다. 4장 주요 내용: 클래스 정의 실제 데이터(instance data) 캡슐화와 자바 조정자(Java modifiers) 메쏘드 선언과 매개변수 전달(parameter passing) 구성자(constructors) 그래픽 개체(graphical objects) 이벤트와 감청자(listeners) 버튼 과 텍스트 필드(buttons and text fields)
Outline 클래스의 해부 캡슐화(Encapsulation) 메쏘드의 해부 그래픽 객체(Graphical Objects) 그래픽 사용자 인테페이스 버튼과 텍스트 필드
클래스 작성 지금까지의 예제에서는 Java 클래스 라이브러리에 미리 정의된 클래스들을 사용하였다. 지금부터는 우리가 작성하는 클래스를 사용하여 프로그램을 디자인 하는 방법을 공부하도록 한다. 메인 메쏘드를 포함하는 클래스가 프로그램의 시작 점이된다. 객체지향 프로그래밍은 객체의 잘 정의된 특성과 기능을 나타나는 클래스의 정의에 기반한다.
클래스와 객체 1장에서 언급했던 것과 같이 객체는 상태(state) 와 행동(behavior)을 갖고 있다. 육면체 주사위를 고려해 보자. 이 주사위의 표면 값이 상태가 될 수 있다. 이 주사위의 기본 적인 행동은 주사위를 굴리는 것이 될 것이다. 소프트웨어에서의 주사위 표현은 위의 상태와 행동을 모델로 하는 Die라는 클래스의 디자인으로 할 수 있다. 이 클래스는 주사위 객체의 청사진이 된다 이 클래스를 사용하여 프로그램 상에서 원하는 만큼의 주사위 객체를 생성할 수 있다.
(Method declarations) 클래스 클래스는 데이터 선언들과 메쏘드 선언들을 갖는다 int size, weight; char category; 데이터 선언들 (Data declarations) 메쏘드 선언들 (Method declarations)
클래스 객체(Object): 클래스로부터 생성 예: 교과서의 Die class 데이터 값: 객체의 상태를 정의 데이터 값: 객체의 상태를 정의 메쏘드의 기능(functionality): 객체의 행동(behavior) 정의 예: 교과서의 Die class faceValue 변수: 주사위의 표면 값을 나타냄 (상태) roll 메쏘드: 1 -6 사이의 임의 값(random number)으로 주사위 굴리기 표현 (행동)
클래스 다양하고 재사용이 가능하도록 다른 데이터들과 메소드를 포함하여 Die class를 디자인 할 수 있다. 프로그램은 주어진 클래스의 모든 기능을 사용할 필요는 없다. RollingDice.java (영: 157쪽, 국: 163쪽) 참조 Die.java (영: 158쪽, 국: 164쪽) 참조
Ex : Rollingdice.java //*************************************************// 사용자-정의 클래스의 생성과 사용을 보여준다. //************************************************* public class RollingDice { //------------------------------------- // 두 개의 Die 객체를 생성하고 그들을 몇 번 굴린다. public static void main (String[] args) Die die1, die2; int sum; die1 = new Die(); die2 = new Die(); die1.roll(); die2.roll(); System.out.println ("Die One: " + die1 + ", Die Two: " + die2); die1.roll(); die2.setFaceValue(4); System.out.println ("Die One: " + die1 + ", Die Two: " + die2); sum = die1.getFaceValue() + die2.getFaceValue(); System.out.println ("Sum: " + sum); sum = die1.roll() + die2.roll(); System.out.println ("New sum: " + sum); }
Ex : Die.java //--------------------------------- // 표면 값 설정. //--------------------------------- // 표면 값 설정. //--------------------------------- public void setFaceValue (int value) { faceValue = value; } //--------------------------------- // 표면 값 반환 public int getFaceValue() return faceValue; // 이 주사위의 스트링 표현 반환 public String toString() String result = Integer.toString(faceValue); return result; /**************************************************** // 1과 6사이의 표면 값을 갖는 하나의 주사위를 나타낸다. //*************************************************** public class Die { private final int MAX = 6; // maximum face value private int faceValue; // current value showing on the die //--------------------------------------- // 구성자(constructor): 초기 표면 값을 설정한다. public Die() faceValue = 1; } // 주사위를 굴리고 결과 값을 반환한다. public int roll() faceValue = (int)(Math.random() * MAX) + 1; return faceValue;
Die 클래스 Die 클래스는 두 개의 데이터 값을 갖는다 Die 클래스는 4개의 메쏘드를 갖는다. MAX 상수: 최대 표면 값 faceValue 변수: 현재 표면 값 Die 클래스는 4개의 메쏘드를 갖는다. roll 메쏘드: Math 클래스의 random 메쏘드를 사용하여 새로운 표면 값을 얻음. setFaceValue 메쏘드: 표면 값 설정 getFaceValue 메쏘드: 현재 표면 값 반환 toString 메쏘드: 현재 표면 값을 스트링으로 반환
toString 메쏘드 객체를 표현하는 모든 클래스는 toString 메쏘드를 정의하여야 한다. 이 메쏘드는 객체가 스트링과 접합되거나 매개변수로 println 메쏘드로 전달될 때 자동으로 호출된다.
구성자(Constructors)/생성자 Die 구성자는 새로운 die 객체의 표면 값을 1 로 초기화 한다. public Die() { faceValue = 1; } 이 장의 뒷 부분에서 구성자에 대해 더 자세히 다루도록 한다.
데이터 영역(Scope) 데이터의 영역(scope of data)은 프로그램에서 그 데이터가 참조(사용) 될 수 있는 영역을 말한다. 클래스 수준(level)에서 선언된 데이터는 클래스의 모든 메쏘드 내에서 참조될 수 있다. 메쏘드 안에서 선언된 데이터는 그 메쏘드 안에서만 참조된다. 메쏘드 안에서 선언된 데이터를 지역 데이터 (local data)라 부른다. 예), Die 클래스의 toString 메쏘드에서 선언된 result 변수는 메쏘드의 local 변수로 다른 곳에서는 참조할 수 없다.
실체 데이터(Instance Data) Die 클래스의 faceValue 변수: 실체 데이터 생성되는 각각의 객체는 자신만의 기억공간을 만든다. 클래스에서 데이터의 타입을 선언하지만 그 데이터를 위한 메모리를 지정하지는 않는다. Die 객체가 생성될 때 새로운 faceValue 변수가 메모리에 생성된다. 클래스의 객체는 메쏘드 정의들을 공유하지만 각각의 메모리 공간을 독립적으로 갖는다. 객체들이 독립적 공간을 갖기 때문에 두 개의 서로 다른 객체는 각기 다른 상태를 가질 수 있다.
실체 데이터(Instance Data) RollingDice 프로그램에서 두 개의 Die 객체는 다음과 같이 표현될 수 있다. faceValue 5 die2 faceValue 2 각각의 Die 객체는 자신의 상태를 나타내는 faceValue 변수를 유지한다.
UML 클래스 다이어그램 UML: Unified Modeling Language UML 다이어그램(diagram) : 클래스와 객체들 사이의 관계 표현에 사용 UML class diagram: 클래스 이름, 데이터의 속성(attributes), 메쏘드의 연산(operations)을 포함하는 사각형으로 각 클래스를 표현. 클래스들을 연결하는 화살표는 클래스들 사이에 관계 (associations)가 있음을 나타냄. 화살표 머리를 갖는 점선은 한 클래스가 다른 클래스의 메쏘드를 사용(uses) 한다는 것을 나타냄.
UML 클래스 다이어그램 RollingDice 프로그램의 UML 클래스 다이어그램: RollingDice Die faceValue : int main (args : String[]) : void roll() : int setFaceValue (int value) : void getFaceValue() : int toString() : String
Outline 클래스의 해부 캡슐화(Encapsulation) 메쏘드의 해부 그래픽 객체(Graphical Objects) 그래픽 사용자 인테페이스 버튼과 텍스트 필드
캡슐화(Encapsulation) 두 가지 관점에서의 객체: 내적(internal) - 클래스가 정의하는 변수들과 메쏘드들의 세부 사항 외적(external) - 객체가 제공하는 서비스들과 프로그램의 다른 부분과의 연동 방법 외적 관점에서 볼 때, 객체는 특정 서비스를 제공하는 캡슐화된 실체 (encapsulated entity) 이다. 이러한 서비스를 제공하는 메쏘드들은 그 객체와 이것을 사용하는 프로그램 사이의 인터페이스(interface)를 정의한다.
캡슐화(Encapsulation) 클라이언트(client)라 불리는 객체는 다른 객체가 제공하는 서비스를 사용하기 위해 그 객체를 부를 수 있다. 객체의 클라이언트는 메쏘드를 호출 함으로써 서비스를 요청하는데 그 서비스들이 어떻게 수행되는지는 모르게 해야 한다. 객체 상태의 모든 변화는 그 객체의 메쏘드를 통해 이루어 져야 한다. 클라이언트의 객체 변수의 직접적인 접근은 불가능해야 하고 그렇지 못할 경우 가능한 한 어렵게 만들어야 한다. 객체는 자치(self-governing )되어야 한다.
캡슐화(Encapsulation) 클라이언트 캡슐화된 객체는 black box로 볼 수 있다. 내부의 일은 클라이언트로부터 감추어져 있다. 클라이언트는 실체 데이터를 관리하는 객체의 인터페이스 메쏘드를 호출 한다. 메쏘드 데이터 클라이언트
가시성 조정자(Visibility Modifiers) Java에서는, 적절한 가시성 조정자(visibility modifiers)를 사용하여 캡슐화를 완성할 수 있다. 조정자(modifier)는 Java의 예약어(reserved word)로 메쏘드나 데이터의 특성을 구체화 한다. 상수를 정의할 때 사용했던 final도 하나의 조정자이다. Java의 3가지 가시성 조정자(visibility modifiers): public, protected, private 상속과 관계된 protected 조정자는 8장에서 소개하도록 한다.
가시성 조정자(Visibility Modifiers) 공용 가시성(public visibility)으로 선언된 클래스의 멤버(데이터+메쏘드)들은 프로그램의 어느 곳에서나 참조가 가능하다. 전용 가시성(private visibility)으로 선언된 클래스의 멤버들은 그 클래스 내에서만 참조가 가능하다. 가시성 조정자가 정의되지 않은 멤버들은 초기설정 조정자(default visibility)를 갖고 같은 페키지 (package) 내의 모든 클래스에서 참조가 가능하다. Java 조정자에 대한 개요는 부록 E(Appendix E)에 나와 있다.
가시성 조정자(Visibility Modifiers) 공용 변수는 클라이언트의 접근과 값의 변경을 허용하기 때문에 캡슐화를 위반한다. 그러므로 실체 데이터 변수는 공용 가시성으로 선언하면 안 된다. (private 로 선언 해야 함) 다만 상수에 공용 가시성을 주는 것은 일반적으로 허용된다. 공용 상수는 클라이언트가 접근하더라도 변경이 불가능 함으로 캡슐화를 위반하지는 않기 때문이다.
가시성 조정자(Visibility Modifiers) 객체의 서비스를 제공하는 메쏘드들은 공용 가시성 (public visibility)으로 선언되어 클라이언트로부터 호출 될 수 있도록 한다. 공용 메쏘드(Public methods)를 때때로 서비스 메쏘드(service methods)라 부른다. 서비스 메쏘드를 보조 하기위한 메쏘드를 지원 메쏘드 (support method)라 부르기도 한다. 지원 메쏘드는 클라이언트로부터 호출되지 안도록 해야 하기 때문에 공용 가시성으로 선언되어서는 안된다.
가시성 조정자(Visibility Modifiers) public private 변수 Variables 메쏘드 Methods 캡슐화 위반 캡슐화 시행 클라이언트에 서비스 제공 클래스 내의 다른 메쏘드 지원
접근 메쏘드(Accessors)와 변이 메쏘드(Mutators) 실체 데이터는 전용 가시성으로 선언되기 때문에 클래스는 보통 데이터 값을 접근하거나 변경할 수 있는 서비스를 제공한다. 접근 메쏘드(accessor method): 변수의 현재 값 반환 변이 메쏘드(mutator method): 변수 값 변경 일반적으로 접근 메쏘드와 변이 메쏘드의 이름은 getX 와 setX의 형태로 이 때 X는 값의 이름이다. 이러한 타입의 메쏘드들은 때때로 “접근자(getters)”와 “설정자(setters)”라고 한다.
변이 메쏘드의 제한(Mutator Restrictions) 변이 메쏘드의 사용은 클래스 작성자에게 클라이언트로 하여금 객체의 상태를 변환할 수 있는 기능을 제공 하기도 한다. 변이 메쏘드는 종종 변수의 값을 특정 한도 안에서 지정할 수 있도록 디자인되기도 한다. 예), Die 클래스의 setFaceValue 변이 메쏘드(mutator)는 faceValue의 유효 값을 1부터 MAX 사이의 값으로 제한 하여야 한다. 5장에서 어떻게 그러한 제한이 설정되는지 소개 될 것이다.