-
GUI / innerclass(내부클래스)language/JAVA 2019. 1. 23. 13:56반응형
그래픽 사용자 인터페이스(graphical user interface, GUI)는 사용자가 편리하게 사용할 수 있도록 입출력 등의 기능을 알기 쉬운 아이콘 따위의 그래픽으로 나타낸 것입니다. 이와 반대 되는 개념으로는 Command Line에 직접 명령어를 입력해서 조작하는 CLI(Command-line Interface) 또는 CUI(Character User Interface) 가 있습니다.
자바에서도 역시 GUI를 이용해 애플리케이션을 만들 수 있습니다. 가장 유명한 것은 awt, swing(+javafx) 같은 툴킷이고 책(head first java)에서는 주로 swing을 다루고 있습니다.
그래픽 인터페이스에 대해 이해하기 위해서 먼저 이벤트와 리스너의 개념에 대해 알아보고 가겠습니다.
자바에서 이벤트는 GUI에서 뭔가 바뀌었을 때 생성되는 객체입니다. 가령 사용자가 버튼을 클릭하거나 콤보박스를 클릭하거나 혹은 문자열을 입력하거나 하는 등의 행동을 하면, 관련있는 이벤트 객체가 생성되게 됩니다.
자바에서의 이벤트 처리
1. 프로그램이 실행중에 운영체제(OS)가 해당 프로그램에서 이벤트가 발생이 되는지를 검사한다.
2. 이때 이벤트가 발생되면 운영체제가 JVM에게 이벤트를 전달하고 JVM은 발생된 이벤트를 처리하기 위하여 이벤트 객체를 생성한다.
3. 그런후 이벤트를 처리하기 위하여 이벤트 객체를 가지고 핸들러를 호출한다.
이렇게 생성된 이벤트 객체를 처리하는 것이 리스너(listener) 입니다.
이건 이벤트 클래스 상속트리 입니다. 모든 이벤트 객체가 EventObject를 확장하고 있는 것을 알 수 있습니다.
EventObject에는 getSource() 메소드를 가지고 있고 이 메소드는 해당 이벤트를 발생하게 만든 소스를 반환합니다. 소스는 어떤 원인(클릭, 키보드 입력 등)에 의해 이벤트가 발생했는지를 말하는 것입니다.
이런식으로 이벤트 객체는 각각 발생한 이벤트에 관한 정보를 저장하고 있습니다.
자바에서 이벤트 객체를 처리하는 것은 리스너(listener) 입니다.
리스너는 인터페이스입니다. 때문에 리스너 인터페이스를 구현하는 클래스와 이벤트 객체를 연결시켜줘야 합니다.
위 코드는 실제로 awt 패키지에 있는 event 패키지를 이용해서 버튼을 클릭했을때 동작하는 간단한 GUI 애플리케이션을 만들어 본 것입니다.
위 코드에서 ActionListener 인터페이스에 있는 actionPerformed 메소드를 구현하고
button 객체를 addActionListener 메소드를 통해 리스너 목록에 등록합니다.(addActionListener의 인자는 ActionListener interface를 구현한 클래스를 전달해야합니다) 이제 버튼에 어떤 액션이 생기면 actionPerformed 메소드가 실행 됩니다.
이 클래스 객체를 생성하면 오른쪽과 같은 창이 뜨고 클릭하게 되면 내용이 바뀌게 됩니다.
컴포넌트 이벤트 처리 3단계
1. 이벤트 소스 결정
하나의 윈도우에는 여러 개의 컴포넌트가 존재할 수 있으므로 실제로 이벤트가 발생되면 처리할 컴포넌트를 결정한다.
2. 이벤트 리스너 작성
이벤트를 실제적으로 처리할 수 있도록 해당 이벤트를 처리 할 이벤트 리스너 인터페이스를 이용해서 이벤트 리스너 클래스를 작성한다.
3. 이벤트 소스와 이벤트 리스너 연결
이벤트 리스너가 작성이되면 리스너와 이벤 트 소스와 연결을 하여 이벤트 소스에서 실제적으로 이벤트가 발생이 되면 처리할 수 있도록 addXXXXListener()함수를 통해 연결을 시켜준다. XXXX부분은 해당 컴포넌트에 붙일 수 있는 리스너 이름을 의미한다. 예를 들어 버튼에 ActionEvent을 처리하기 위하여 버튼에다가 addActionListener를 붙이는 경우이다.
여기서는 이벤트가 발생한 클래스에서 바로 처리를 해 주는 방법을 썼지만 리스너를 다른클래스로 독립시킬 수 도 있습니다.
ActionListener를 구현하는 다른 클래스를 독립적으로 만든 코드입니다.
호출하는 클래스 객체를 수정하게 됩니다.
작동은 앞의 코드와 똑같습니다.
그리고 내부 클래스를 이용할 수 있습니다.
내부 클래스는 다른 클래스 안에 정의 된 클래스를 의미합니다.
내부클래스는 외부 클래스의 모든 메소드와 변수를 사용할 수 있습니다.
이 때 private으로 지정된 메소드와 변수도 모두 접근 가능합니다.
마치 내부 클래스 안에서 정의한 변수와 메소드인 것 처럼 사용이 가능합니다.
하지만 반대로 외부 클래스에서 내부 클래스로 접근할 때는 서로 다른 클래스 처럼 사용해야 합니다.
다시말해 내부 클래스는 외부 클래스에 자유롭게 접근이 가능하고 외부 클래스에는 내부클래스의 인스턴스를 만들 수 있다 라는 것입니다.
그리고 다른 클래스 에서는 내부클래스에 접근할 수 없고 외부 클래스의 인스턴스를 통해서만 접근이 가능합니다.
따라서 내부클래스는 외부클래스의 인스턴스가 존재해야지만 제역할을 할 수 있습니다.
외부 클래스의 인스턴스 없이 내부클래스에 접근하고자 한다면 정적클래스(static class)를 사용하면 됩니다.
하지만 정적 클래스는 외부의 정적 메소드와 변수에만 접근 가능하다는 단점이 있습니다.
(주로 외부 클래스의 클래스 메소드로 사용되는 목적으로 정적 클래스를 사용하게 됩니다. 반대로 인스턴스 클래스의 경우에는 외부 클래스의 인스턴스 변수나 메서드에 사용됩니다.)
클래스를 메소드나 초기화 블록 안에서 선언하는 지역 클래스 (Local Class)의 개념도 존재합니다.
이 경우 지역 클래스는 해당 메소드 블록 안에서만 접근이 가능하게 됩니다.
마지막으로 익명 클래스(Anonymous Class)를 알아보겠습니다.
익명 클래스는 선언과 동시에 객체를 생성하는 클래스 입니다.
객체는 딱 한번만 생성되고 일회용으로 사용되어집니다.
따라서 생성자를 사용할 수 없고, 하나의 클래스 혹은 인터페이스를 상속받아 만들어지게 됩니다.
(저같은 경우는 Collection 객체를 sort시킬 때 Comparator 클래스를 만들어서 쓴 적이 있습니다.)
이런 내부 클래스를 사용하게 되면
서로 관련있는 클래스를 논리적으로 묶어서 표현하게 되고 외부에서 내부 클래스에 접근할 수 없기 때문에 코드의 캡슐화가 증가됩니다.
그리고 클래스 내에서 같은 인터페이스를 여러번 구현할 수 있게 만들 수 있습니다. 이렇게 되면 똑같은 메소드를 여러번 구현할 수 있게 됩니다.
가령 앞에서 봤던 GUI에 버튼이 여러개라면 각각의 버튼에 개수만큼 똑같은 메서드를 만들 수 있게 됩니다.
그리고 외부클래스와는 다른 상속관계 (A는 B다 관계)를 가진 클래스를 내부클래스로 만들면 객체의 유연성이 증가하게 됩니다. 가령 Dog 객체가 Button 객체처럼 행동해야 하는 경우가 있다면 내부클래스를 이용해서 구현할 수 있습니다.
반응형'language > JAVA' 카테고리의 다른 글
네트워크, 소켓 (0) 2019.01.30 serialization(직렬화) (0) 2019.01.23 예외 처리(Exception) (0) 2019.01.23 정적 변수, 정적 메소드(static) (0) 2019.01.23 자바에서 변수를 다루는 법 (0) 2019.01.17