Java의 정석 제 7 장 객체지향개념 II-1 Java 정석 2008. 7. 7 남궁성 강의 Chapter 7. 객체지향개념 II http://www.javachobo.com Java의 정석 제 7 장 객체지향개념 II-1 안녕하십니까? 자바의 정석의 저자 남궁성입니다. 지금부터 제7장 객체지향개념2에 대한 강의를 시작하겠습니다. 2008. 7. 7 남궁성 강의 castello@naver.com
객체지향개념 II-1 객체지향개념 II-2 객체지향개념 II-3 Java 1. 상속 2. 오버라이딩 의 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 1. 상속 객체지향개념 II-1 2. 오버라이딩 3. package와 import 4. 제어자 객체지향개념 II-2 5. 다형성 7장도 분량이 많기 때문에 이와 같이 3개의 부분으로 나누어서 강좌를 제작하였습니다. 이번엔 첫번째 부분인 상속, 오버라이딩, 패키지와 import에 대해서 설명드리겠습니다. 6. 추상클래스 객체지향개념 II-3 7. 인터페이스
Java 1. 상속(inheritance) 1.1 상속의 정의와 장점 1.2 클래스간의 관계 1.3 클래스간의 관계결정하기 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 1. 상속(inheritance) 1.1 상속의 정의와 장점 1.2 클래스간의 관계 1.3 클래스간의 관계결정하기 1.4 단일 상속(single inheritance) 1.5 Object클래스 2. 오버라이딩(overriding) 3. package와 import 2.1 오버라이딩이란? 3.1 패키지(package) 세부목차인데요. 이 강의는 이와 같은 순서로 진행될 것입니다. 강의형식에 맞게 수정하였기 때문에 책의 목차와는 좀 다르지만 내용은 거의 같습니다. 2.2 오버라이딩의 조건 3.2 패키지의 선언 2.3 오버로딩 vs. 오버라이딩 3.3 클래스패스 설정 2.4 super 3.4 import문 2.5 super() 3.5 import문의 선언
1. 상속(inheritance) Java 정석 의 Chapter 7. 객체지향개념 II http://www.javachobo.com 1. 상속(inheritance)
1.1 상속(inheritance)의 정의와 장점 Java 의 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 1.1 상속(inheritance)의 정의와 장점 ▶ 상속이란? - 기존의 클래스를 재사용해서 새로운 클래스를 작성하는 것. - 두 클래스를 조상과 자손으로 관계를 맺어주는 것. - 자손은 조상의 모든 멤버를 상속받는다.(생성자, 초기화블럭 제외) - 자손의 멤버개수는 조상보다 적을 수 없다.(같거나 많다.) class 자손클래스 extends 조상클래스 { // ... } 6장에서 객체지향개념에 대한 기본적인 내용에 대해서 알아봤는데요. 7장에서는 본격적인 객체지향개념... 상속, 다형성, 캡슐화, 추상화, 인터페이스 등에 대해서 학습할 것입니다. 첫번째로 여러 객체지향개념의 가장 기초가 되는 상속에 대해서 알아보겠습니다. 간단히 얘기해서... 상속은 클래스를 정의할 때 기존의 클래스를 이용하는 것입니다. 기존의 클래스를 재사용해서 새로운 클래스를 만드는 것이지요. 상속을 통해 새로운 클래스를 정의하는 방법은 아주 쉽습니다. 새로 정의할 클래스 이름 뒤에 키워드 extends를 써주고, 상속받고자하는 클래스를 적어주기만 하면 됩니다. 나머지는 일반적으로 클래스를 정의할 때와 똑같고요... 그러면 이 두 클래스는 서로 조상과 자손의 관계가 맺어지고, 자손은 조상의 모든 멤버, 즉 멤버변수와 메서드를 그대로 상속받게 됩니다. 이 때, 자손은 조상의 모든 멤버를 그대로 상속받게 될 뿐.... 원하는 것만 골라서 상속받을 수가 없습니다. 그래서 자손의 멤버개수는 조상의 멤버개수보다 적을 수가 없습니다. 항상 같거나 많을 수 밖에 없겠죠... 다만... 생성자와 초기화 블럭은 상속되지 않습니다. 각 클래스의 생성자에는 자신에 정의된 멤버변수만을 초기화하는 코드와 조상의 생성자를 호출하는 코드를 넣어서... 상속받은 멤버변수들은 조상의 생성자에 의해 초기화되도록 합니다. 2차원 좌표의 한 점을 표현하기 위한 Point클래스가 이와 같이 정의되어 있을 때... 3차원 좌표의 한 점을 표현하기 위한 Point3D클래스는... 왼쪽과 같이... x,y,z.... 모두 3개의 정수값으로 정의할 수 도 있지만... 기존의 Point클래스로부터 상속받아서 정의하면.... 오른쪽과 같이 할 수 있습니다. 자손클래스는 조상클래스에 정의된 멤버들을 그대로 상속받기 때문에... Point3D클래스는 조상인 Point클래스에 정의된 멤버변수 x와 y를 모두 상속받게 됩니다. 그래서 Point3D클래스에는... 새로운 멤버변수 z만 정의하면 되는 것입니다. 즉, 자손 클래스에는 추가적인 부분만 정의하면 되는 것입니다. 각 클래스의 멤버를 다이어그램으로 그려보면... 맨 오른쪽 그림과 같습니다. 항상 자손인 Point3D클래스가 조상인 Point클래스를 완전히 포함하고 있죠. 만일 Point3D클래스를 조상으로 하는 다른 클래스를 정의한다면... 이 두 클래스의 모든 멤버를 포함하는... 보다 확장된 형태가 될 것입니다. 좀전에 얘기한 것과 같이... 자손은 조상의 모든 멤버를 그대로 상속받기 때문에 자손의 멤버 개수는 절대로 조상의 멤버 개수보다 적을 수 없습니다. 항상 같거나 많죠. 그래서...상속에 상속을 거듭할 수록... 멤버의 개수가 점점 많아집니다. 상속에 사용되는 키워드 extends의 의미 역시... 조상클래스를 확장한다...는 것이고요. 이 두 개의 Point3D클래스 모두... 인스턴스를 생성하면 3개의 정수값을 저장할 수 있는 공간이 만들어진다는 것은 같지만... 왼쪽의 Point3D클래스와 Point클래스에는 아무런 관계가 없는 반면... 오른쪽의 코드는 Point클래스가 조상클래스가 되고 Point3D클래스는 자손클래스가 되어서... 이 두 클래스간에는 조상-자손의 관계가 성립된다는 것이 다른 점입니다. 코드가 같다고 해서... 무조건 재사용해야 하는 것은 아니고요... 기존의 클래스를 바탕으로 보다 확장된 기능의 클래스를 설계할 때... 상속을 이용하시면 됩니다. 아무것도 없는 상태에서 클래스를 새로 만드는 것보다... 자신이 원하는 기능과 가장 유사한... 기존의 클래스를 상속받아서... 기능을 추가적으로 정의해주는 것이 편리하겠죠. 그래서... 조상클래스를... 다른 클래스를 정의하는데... 바탕이 된다고 해서 base클래스 또는 기반 클래스라고도 합니다. z x y Point Point3D 5 5
1.2 클래스간의 관계 – 상속관계(inheritance) Java 의 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 1.2 클래스간의 관계 – 상속관계(inheritance) - 공통부분은 조상에서 관리하고 개별부분은 자손에서 관리한다. - 조상의 변경은 자손에 영향을 미치지만, 자손의 변경은 조상에 아무런 영향을 미치지 않는다. Child GrandChild Parent Child2 GrandChild 이와 같이 4개의 클래스가 정의되어 있을 때... 이 클래스들의 상속관계를 간략한 그림으로 그리면 아래와 같습니다. 이것을 상속계층도라고 하는데요... 상속계층도를 그려보면... 클래스간의 관계를 쉽게 이해할 수 있습니다. 상속관계에는 조상과 자식관계만 있을 뿐, 형제와 같은 관계는 없습니다. Child와 Child2클래스는 Parent클래스라는 공통 조상을 가지고 있지만... 이 두 클래스는 아무런 관계도 아닙니다. 만일 Child와 Child2클래스에 새로운 메서드를 추가해야 한다면... 이 두 클래스에 각각 추가하는 것보다... 이들의 공통조상인 Parent클래스에 추가하는 것이 좋습니다. 예를 들어... Swing이나 AWT와 같은 윈도우 프로그래밍에서는 한 화면이 하나의 클래스인데요... 갑자기 프로그램의 모든 화면의 기본 디자인을 바꾸기로 결정되었다면... 프로그램의 모든 화면을 일일이 다 바꿔야 할테니... 개발자에게는 정말 피곤한 일이겠죠. 그러나 기본 공통 화면을 만들어 놓고, 모든 화면이 이 공통화면을 상속받도록 했다면... 모든 화면을 일일이 고치는 대신... 이 공통화면 하나만 수정하면 될 것입니다. 여러 클래스의 공통적인 멤버들을 뽑아내서... 조상클래스로 만들어 상속받도록 하고... 공통적인 부분은 조상클래스에서 관리하고... 개별적인 부분은 자손클래스에서 관리하도록 하는 것이 좋습니다. 만일 Parent클래스에 새로운 멤버변수 x가 추가되면 어떤 클래스들이 영향을 받을까요... 예... 맞습니다. Parent의 모든 자손클래스들... Child, Child2, GrandChild에 멤버변수 x가 새로 추가된 셈이 됩니다. 이처럼... 조상클래스의 변경은 모든 자손클래스와 자손의 자손클래스까지 영향을 미치지만... 자손의 변경은 조상에게 아무런 영향을 미치지 않습니다. 예를 들어서... Child클래스에 새로운 멤버변수 y가 추가되었다면... Child클래스의 조상인 Parent클래스는 아무런 영향을 받지 않습니다. Child클래스의 자손인 GrandChild클래스만 영향을 받을 뿐입니다. 이처럼 조상의 변경은 자손대대로 영향을 미치기 때문에... 원하지 않는 클래스에 영향이 미치지 않도록... 상속관계를 세분화 해서 잘 관리해야 합니다. Parent Child2 Child 6 6
1.2 클래스간의 관계 – 포함관계(composite) Java 의 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 1.2 클래스간의 관계 – 포함관계(composite) ▶ 포함(composite)이란? - 한 클래스의 멤버변수로 다른 클래스를 선언하는 것 - 작은 단위의 클래스를 먼저 만들고, 이 들을 조합해서 하나의 커다란 클래스를 만든다. 상속 이외에도 클래스간의 관계를 맺어주는 방법으로 ‘포함’이 있습니다. 포함’이라는 것은... 클래스를 정의할 때, 멤버변수로 다른 클래스 타입의 참조변수를 선언하는 것입니다. 예를 들어 Circle이라는 클래스가 왼쪽과 같이 정의되어 있을 때... 기존의 Point클래스를 이용해서 포함관계로 변경하면 오른쪽과 같은 코드가 됩니다. int타입의 멤버변수 x와 y를 선언하는 대신... Point클래스 타입의 참조변수 c를 선언한 것입니다. 인스턴스를 생성하면 양쪽의 코드 모두 세 개의 int값을 저장할 수 있는 공간이 생기는... 똑같은 결과를 얻지만... 기존의 코드를 재사용한 오른쪽의 코드가 좀더 바람직하다고 할 수 있습니다. Circle클래스가 간단해서 이 두 코드의 차이가 별로 크게 와 닿지 않겠지만... 클래스가 복잡할 수록... 오른쪽과 같이... 관련된 멤버들을 묶어서 여러 개의 작은 클래스로 정의하고 이들을 포함시키는 것이... 코드를 간결하고 이해하기 쉽게 만들어줄 뿐만 아니라... 이 클래스들은 다른 곳에서 재사용될 수도 있고... 나중에 변경사항이 생기더라도... 코드를 한 곳에서 관리가 가능하다는 장점이 있습니다. 예를 들어... 자동차를 만들 때... 자동차를 구성하는 엔진이나 문과 같은 주요부분을 먼저 만들어 놓고 이들을 조립하는 것처럼... Car클래스를 정의할 때도... Engine과 Door클래스를 미리 정의해 놓고 이들을 포함시키도록 하는 것이 좋습니다. 7 7
Java 1.3 클래스간의 관계결정하기 – 상속 vs. 포함 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 1.3 클래스간의 관계결정하기 – 상속 vs. 포함 - 가능한 한 많은 관계를 맺어주어 재사용성을 높이고 관리하기 쉽게 한다. -‘is-a’와 ‘has-a’를 가지고 문장을 만들어 본다. 클래스를 정의할 때... 관련된 클래스들은 최대한 관계를 많이 맺어주어서 재사용성을 높여야 합니다. 클래스간의 관계를 상속으로 할 것인지 포함으로 할 것인지 결정하는 것이 아직은 쉽지 않으실 텐데요. 가장 간단한 방법은 ‘is-a’와 ‘has-a’를 가지고 문장을 만들어보는 것입니다. 그럼, 앞서 나온 Circle클래스와 Point클래스를 가지고 문장을 만들어봅시다. is-a를 가지고 문장을 만들면... Circle is a Point. 즉, 원은 점이다. has-a를 가지고 문장을 만들면... Circle has a Point. 원은 점을 가지고 있다. 가 됩니다. 어느 문장이 더 자연스럽나요? 여기서 점은... 원의 중심을 의미하는 원점을 뜻한다고 했을 때... 원을 구성하는 것은 원점과 반지름이니까... Circle ahs a Point 즉, 원은 원점을 가지고 있다... 가 더 자연스러운 문장이라고 할 수 있습니다. 그래서... 왼쪽의 코드와 같이 Circle클래스가 Point클래스를 상속받도록 하는 것 보다... Point클래스를 포함시키도록 하는 것이 더 적절합니다. 사실... 실제 프로그래밍을 하다 보면... 이처럼 문장을 만들어도 판단하기 어려운 경우가 많은데요. 대부분의 경우 포함관계이고요... 기존의 클래스에 새로운 기능이 추가된 새로운 클래스를 만들 때는 상속관계를 맺어주면 됩니다. 상속이나 포함의 공통적인 목적은... 코드를 재사용함으로써 서로 유기적으로 연결되도록 하는 것이고... 그렇게 함으로써 한 곳의 변경이 다른 곳에 자동적으로 영향을 미치도록 하여... 작업의 양을 줄여주고... 오류의 가능성을 낮춰주는 것입니다. 상속관계는 포함관계보다 객체지향개념적으로... 좀더 중요한 의미를 갖습니다... 포함관계는 간단히 얘기해서 재사용성을 높인다는 정도인데... 상속관계는 앞으로 배우게 될 다형성과도 깊은 관계가 있고... 상속계층도에 포함되므로... 앞서 살펴본 것과 같이 조상의 변화에 따라 모든 자손들이 영향을 받기 때문에... 상속관계를 잘못 맺어주면... 원하지 않는 영향을 줄 수도... 받을 수도 있습니다. 그래서... 상속관계를 맺어줄 때는 좀더 신중하게 결정해야 합니다. 8 8
Java 1.3 클래스간의 관계결정하기 – 예제설명 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 1.3 클래스간의 관계결정하기 – 예제설명 - 원(Circle)은 도형(Shape)이다.(A Circle is a Shape.) : 상속관계 - 원(Circle)은 점(Point)를 가지고 있다.(A Circle has a Point.) : 포함관계 Shape Circle Triangle 도형을 의미하는 Shape클래스와 점을 의미하는 Point클래스가 이와 같이 정의되어 있다고 했을 때... 이들을 이용해서 Circle클래스와 Triangle클래스를 정의한 예제입니다. Circle이나 Triangle 모두 도형이기 때문에... is-a 관계가 성립하므로... Shape클래스를 상속받도록 하고... 원은 원점을 가지고 있고... 삼각형도 3개의 점으로 구성되어 있기 때문에... Point클래스를 포함하도록 하였습니다. Triangle클래스에는 Point타입의 변수를 3개 선언해도 되지만... 여기서는 객체배열의 예를 보여주기 위해서... Point타입의 배열을 선언했습니다. 기본 생성자를 이용해서 Circle인스턴스를 생성하면... Circle클래스의 기본생성자가 다른 매개변수가 있는 생성자를 호출합니다. 그래서... 원점의 좌표가 0,0이고 반지름이 100인 Circle인스턴스가 만들어집니다. 두번째줄은 원점의 좌표가 150,150이고 반지름이 50인 Circle인스턴스를 만드는 것이고요. 그 다음엔... 3개의 Point인스턴스가 담긴 Point배열을 생성하고... 이것을 Triangle의 생성자의 매개변수로 넘겨줌으로써 Triangle인스턴스를 생성합니다. 그러면... 이 생성자가 호출되겠죠... 배열의 주소를 넘겨 받아서... Triangle클래스의 멤버변수인 p에 저장합니다. 9 9
Java 1.3 클래스간의 관계결정하기 – 예제설명2 정석 의 Chapter 7. 객체지향개념 II 10 10 http://www.javachobo.com 1.3 클래스간의 관계결정하기 – 예제설명2 책의 예제 중에서 질문을 많이 받은 부분이라서... 좀 더 자세히 설명드리고자 합니다. 한 벌의 카드를 의미하는 Deck클래스를 정의하였습니다. 카드 한 벌은 여러 장의 카드로 이루어져 있으니까... 여러 개의 Card인스턴스를 담을 수 있도록 Card타입의 배열을 선언하였습니다. Card클래스는 지면관계상 생략하였습니다. 책을 참고하시기 바라고요. 카드 한 벌이 몇 개의 카드로 구성되어 있는지에 따라서 배열의 크기가 달라지도록 하였습니다. 이처럼... 값을 직접 사용하기 보다는 이 값이 어떤 값인지... 알 수 있게... 변수나 상수에 담아놓고 사용하는 것이 좋습니다. 먼저 Deck인스턴스를 생성하면... Deck클래스의 생성자가 호출되고... 생성자에서는... 반복문을 이용해서 52개의 Card인스턴스를 생성해서 Card배열에 담습니다. Card배열이 생성되었다고 해서... Card인스턴스까지 생성되어 있는 게 아니라는 것 주의하시기 바랍니다. 그 다음에 Deck에서 pick메서드를 호출해서... 카드 한 장을 꺼냅니다. random메서드를 이용해서 0~51범의 값을 얻어서... 매개변수가 있는 pick메서드를 호출합니다. 10을 얻었다고 가정하면... index의 값이 10이 되겠죠. pick메서드는 Card배열에서 지정된 위치에 있는 카드를 반환합니다. 여기서 index의 값은 Card배열의 범위인 0과 51사이의 값이어야 하겠죠... 그래서... 간단히 나머지 연산자를 이용해서 범위를 벗어나지 않도록 했습니다... 사실은 좀더 정확하게 값의 범위를 벗어나지 않도록 해야 하는데... 복잡하지 않도록 간단히 이 정도로만 처리했습니다. 여러분들이 좀더 정확한 코드를 작성해 보시기 바랍니다. 10%52의 결과는 10이니까... Card배열의 11번째에 저장된 Card인스턴스가 반환됩니다. 그 다음에.. Deck인스턴스의 shuffle메서드를 호출해서 저장된 카드의 순서를 바꿉니다. shuffle메서드는 random메서드를 이용해서... Card배열에 저장된 Card인스턴스의 순서를 바꿉니다. 두 변수의 값을 변경하려면... 임시변수가 하나 더 있어야 한다는 것... 이해하시죠? 컵A에 우유, 컵B에 주스가 담겨 있을 때... 이 두 컵의 내용물을 서로 바꾸려면... 어떻게 해야 하는 지와 같습니다. temp라는 그릇에 우유를 옮기고... 주스를 컵A로 옮기고... temp의 우유를 컵B에 옮기면 됩니다. 여기서는 배열의 첫번째 요소와 임의의 위치에 있는 요소와 자리를 바꾸는 겁니다. 로또에서 1~45의 번호가 적힌 공을 넣고... 위치를 계속 바꿔서 섞는 것과 비교해서 이해하시면 쉬울 겁니다. 그 다음에는... Deck에서 pick메서드를 호출 해서 55번째 카드를 꺼냅니다. pick메서드의 매개변수 index의 값이 55가 되고... CARD_NUM으로 나머지 연산을 하면... CARD_NUM의 값이 52이니까... 3이 되겠죠. 그래서 c[3]에 저장된 Card인스턴스가 반환되어 참조변수 c2에 저장됩니다. 10 10
1.4 단일상속(single inheritance) Java 의 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 1.4 단일상속(single inheritance) - Java는 단일상속만을 허용한다.(C++은 다중상속 허용) - 비중이 높은 클래스 하나만 상속관계로, 나머지는 포함관계로 한다. 상속 포함 자바는 단 하나의 조상으로부터만 상속받을 수 있는데요. 이 것을 단일 상속이라고 합니다. 참고로... 자바보다 먼저 나온 객체지향언어 C++에서는 여러 조상으로부터 상속받을 수 있는 다중상속을 허용합니다. 다중상속을 허용하면 여러 클래스로부터 상속받을 수 있기 때문에 더 쉽게 클래스를 정의할 수 있지만... 조상이 많아질 수록... 상속계층도가 너무 복잡해져서... 클래스간의 관계를 관리하기 어려워집니다. 이렇게 되면... 상속의 장점이 사라져 버리죠... 그리고... 서로 다른 조상으로부터 같은 이름의 멤버를 상속받는 경우... 충돌의 문제도 있습니다. 이미 C++에서 경험한 다중상속의 이러한 문제들 때문에... 자바는 단일 상속만을 허용하도록 만들어진 것입니다. 그래서 이 코드와 같이... TVCR이라는 클래스를 작성할 때... extends 뒤에 TV와 VCR 두 개의 조상클래스를 지정하면 좋겠지만... 둘 중에 비중이 높은 클래스 하나만을 선택해서 적을 수 있습니다. 여기서는 TV클래스를 상속받도록 하였습니다. 대신... VCR클래스는 멤버변수로 포함시키고... 내부적으로 VCR인스턴스를 사용하면 됩니다. VCR클래스에 정의된 멤버들을 TVCR클래스에 똑같이 정의하고... 메서드의 경우... 코드를 작성할 필요없이... 포함시킨 VCR인스턴스의 메서드를 호출하기만 하면되겠죠. 이렇게 하면 다중상속에 비해서 코드가 좀 길어지긴 했지만... 그럭저럭 큰 불편없이 처리가 가능합니다. 11 11
1.5 Object클래스 – 모든 클래스의 최고조상 Java 의 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 1.5 Object클래스 – 모든 클래스의 최고조상 - 조상이 없는 클래스는 자동적으로 Object클래스를 상속받게 된다. - 상속계층도의 최상위에는 Object클래스가 위치한다. - 모든 클래스는 Object클래스에 정의된 11개의 메서드를 상속받는다. toString(), equals(Object obj), hashCode(), ... Object클래스는 모든 클래스의 최고 조상입니다. 예를 들어서 왼쪽과 같이... Tv클래스와... Tv클래스를 조상으로 하는 CaptionTv클래스가 정의되어 있을 때... 이 코드를 컴파일 하면... 오른쪽과 같이... Tv클래스가 Object클래스를 상속받도록 는 자동적으로 변경됩니다. 이렇게 함으로써 모든 클래스의 최고조상이 Object클래스가 되도록 합니다. 보통 클래스간의 상속관계를 나타낼 때 최고 조상인 Object클래스를 생략하곤 하지만... 실제로는 그림과 같이... 모든 상속계층도의 맨 위에는 Object클래스가 위치합니다. 그래서... 모든 클래스에서... Object클래스에 정의된 11개의 메서드를 사용할 수 있는데요. 대표적인 것이 toString(), equals(), hashCode()같은 것들이 있습니다. Object클래스에 대해서는 9장에서 자세히 알아볼 것이고요... 여기서는 모든 클래스의 최고 조상이 Object클래스라는 것과... 이 클래스에 정의된 toString(), equals()와 같은 메서드를 어느 클래스에서나 사용할 수 있다는 정도만 알아두고 넘어가시기 바랍니다. Object Tv CaptionTv 12 12
2. 오버라이딩(overriding) Java 정석 의 Chapter 7. 객체지향개념 II 13 http://www.javachobo.com 2. 오버라이딩(overriding) 13
Java 2.1 오버라이딩(overriding)이란? 의 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 2.1 오버라이딩(overriding)이란? “조상클래스로부터 상속받은 메서드의 내용을 상속받는 클래스에 맞게 변경하는 것을 오버라이딩이라고 한다.” * override - vt. ‘~위에 덮어쓰다(overwrite).’, ‘~에 우선하다.’ 오버라이딩은... 조상으로부터 상속받은 메서드의 내용을 자손에 맞게 변경하는 것을 말합니다. 조상으로부터 상속받은 메서드를 그대로 사용하기도 하지만... 경우에 따라서는 자손클래스에 맞게 내용을 변경해야 할 때가 있습니다. 그럴 때, 오버라이딩이 필요한 것이죠. 상속 받을 때... 상속받고 싶은 멤버만 임의로 선택할 수 없기 때문에... 조상의 모든 멤버를 무조건 받을 수 밖에 없습니다. 그래서 일단 상속은 받고... 상속받은 메서드와 똑같은 메서드를... 내용만 다르게 해서 자손클래스에 정의합니다. 이것이 바로 오버라이딩입니다. 이 때는 똑같은 메서드를 중복해서 정의했다는 에러가 발생하지 않습니다. 오버라이드의 사전적 의미는 ~위에 덮어쓰다, ~에 우선하다’이고요. 여기서는 조상으로부터 상속받은 메서드의 내용을 덮어쓴다고 이해하시면 됩니다. 코드를 보시면... 하나의 2차원 좌표를 표현하기 위한 Point클래스가 정의되어 있습니다. 이 클래스에는 2차원 좌표값을 저장하기 위한 멤버변수 x와 y... 그리고 getLocation이라는 좌표의 위치정보를 반환하는 메서드가 있습니다. 이 메서드를 호출하면 x와 y의 값을 문자열로 반환합니다. 그 아래에는 Point클래스를 조상으로 하는 Point3D클래스를 정의하였는데요. 이 클래스는 3차원 좌표를 표현하기 위한 것입니다. 그래서 멤버변수 z를 새로 추가하였습니다. 조상인 Point클래스로부터 상속받은 getLocation메서드는 Point3D클래스에서 그대로 사용할 수 없습니다. Point3D클래스의 getLocation메서드는 2차원좌표가 아닌 3차원좌표를 문자열로 반환해야 하기 때문이죠. 그래서... 상속받은 getLocaiton메서드를 Point3D클래스에 맞게 x,y,z의 값을 문자열로 반환하도록 재정의 하였습니다. 이 것이 바로 오버라이딩입니다. Point클래스를 사용하던 사람들은... 새로 작성된 Point3D클래스가 Point클래스의 자손이므로... Point3D인스턴스에 대해 getLocation메서드를 호출하면... Point클래스의 getLocation메서드가 그랬듯이... 좌표값을 문자열로 얻을 수 있을 것이라고 기대할 것입니다. 그래서... 이와같은 경우에는 새로운 메서드를 제공하는 것보다... 이처럼 오버라이딩을 하는 것이 올바른 선택입니다. 14 14
Java 2.2 오버라이딩의 조건 정석 1. 선언부가 같아야 한다.(이름, 매개변수, 리턴타입) Chapter 7. 객체지향개념 II http://www.javachobo.com 2.2 오버라이딩의 조건 1. 선언부가 같아야 한다.(이름, 매개변수, 리턴타입) 2. 접근제어자를 좁은 범위로 변경할 수 없다. - 조상의 메서드가 protected라면, 범위가 같거나 넓은 protected나 public으로만 변경할 수 있다. 3. 조상클래스의 메서드보다 많은 수의 예외를 선언할 수 없다. 오버라이딩을 구현하기 위해서는... 다음과 같이 3가지 조건을 지켜야 합니다. 먼저 선언부가 같아야합니다. 오버라이딩은 메서드의 내용만을 변경하는 것이기 때문에... 선언부는 상속받은 메서드와 정확히 일치해야합니다. 만일 매개변수가 달라지면... 오버라이딩이 아니라 오버로딩이 되어버립니다. 재정의가 아니라 완전히 새로운 메서드가 하나 추가되는 것이지요. 두 번째로... 접근제어자를 좁은 범위로 변경해서는 안된다는 것입니다. 오버라이딩을 할 때는 선언부를 똑같이 해야하지만... 접근제어자는 변경할 수 있습니다. 접근제어자는 멤버변수나 메서드 앞에 붙어서 접근범위를 지정하는 것인데요... 바로 다음에 배울 내용이라서 지금은 이해가 잘 안가시겠지만... 일단 오버라이딩 할 때... 접근제어자를 변경할 수 있지만, 좁은 범위로 변경해서는 안된다고만 알아두고 넘어가시기 바랍니다. 세번재도... 여러부들이 아직 안배우신 건 데요... 조상클래스의 메서드 보다 많은 수의 예외를 선언할 수 없다는 것입니다. 메서드에는... 메서드를 수행하는 동안 이러이러한 예외상황이 발생할 수 있다는 것을 알려주기 위해 예외를 선언할 수 있습니다. 그 예외의 개수가 오버라이딩하려는 메서드, 즉 덮어쓰려는 메서드보다 더 많아서는 안된다는 것입니다. 여기서 주의해야 할 점은... 단순히 개수 문제가 아니라는 것입니다. Child클래스는 조상의 parentMethod보다 적은 수의 예외를 선언해서 오버라이딩 했습니다. 오버라이딩을 잘 했죠. Child2클래스 역시 조상의 parentMethod보다 적은 수의 예외를 선언해서 오버라이딩 했지만... Exception은 오버라이딩할 조상의 메서드에는 선언되어 있지 않은 예외이기 때문에... 안됩니다. 조상의 메서드에 선언된 IOException과 SQLException중의 하나이어야 한다는 점... 주의하시기 바랍니다. 이 중에서 제일 중요한 것은 첫번째 조건... 선언부가 같아야 한다는 것이고요... 나머지는 여러분들이 아직 배우지 않은 내용들이 있어서 완전히 이해하기는 어렵겠지만... 접근제어자를 좁은 범위로 변경할 수 없다는 것과 더 많은 수의 예외를 선언할 수 없다는 것을 간단히 외우고 넘어가시면 좋을 것 같습니다. 마지막으로... 당연한 얘기인데... static메서드를 인스턴스 메서드로, 또는 그 반대로 오버라이딩 할 수 없습니다. 15 15
Java 2.3 오버로딩 vs. 오버라이딩 정석 의 Chapter 7. 객체지향개념 II http://www.javachobo.com 2.3 오버로딩 vs. 오버라이딩 많은 분들이 오버로딩과 오버라이딩을 좀 헷갈려하시는 경향이 있어서... 이 둘을 비교해볼까 합니다. 간단히 얘기해서... 오버로딩은 기존에 없는 완전히 새로운 메서드를 정의하는 것이고... 오버라이딩은 기존의 상속받은 메서드의 내용을 변경하는 것입니다. 즉, 오버로딩과 오버라이딩의 차이는 new와 change의 차이라고 생각하시면 쉽습니다. Parent클래스가 있고... 이를 조상으로 하는 Child클래스가 있을 때... Child 클래스의 어떤 메서드가 오버로딩인지 또는 오버라이딩인지 한번 생각해보세요... 첫번째 메서드는 조상의 parentMethod와 선언부가 같으니까... 재정의, 즉 오버라이딩이고요. 두번째 메서드는 메서드의 이름은 같고... 매개변수가 다르니까... 오버로딩입니다. 네번째 childMethod는 바로 위의 메서드와 이름이 같고 매개변수가 다르니까 오버로딩이고요. 다섯번째 메서드는 같은 클래스 내에서 똑같은 선언부를 가진 메서드가 이미 정의되었으므로... 중복정의 에러가 발생합니다. 앞으로 오버로딩과 오버라이딩을 별로 어렵지 않게 구별하실 수 있으리라 생각합니다. 16 16
Java 의 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 2.4 super – 참조변수(1/2) ▶ this – 인스턴스 자신을 가리키는 참조변수. 인스턴스의 주소가 저장되어있음 모든 인스턴스 메서드에 지역변수로 숨겨진 채로 존재 ▶ super – this와 같음. 조상의 멤버와 자신의 멤버를 구별하는 데 사용. 전에 참조변수 this에 대해서 배운 것... 기억나시죠? 이번엔 참조변수 super에 대해서 배우겠습니다. this나 super나 똑같습니다. this가 지역변수와 멤버변수를 구별하는 데 사용된 것처럼... super는 상속받은 멤버와 자신의 멤버를 구별하는 데 사용됩니다. 왼쪽 코드 중에서... 위에 있는 코드를 먼저 보면... Parent클래스가 있고...이 클래스를 상속받는 Child클래스가 있습니다. Parent와 Child에 똑같이 멤버변수 x가 선언되어 있습니다. 이처럼 조상의 멤버변수와 같은 이름의 변수를 자손의 멤버변수로 중복해서 선언하는 것이 가능합니다. 인스턴스가 생성되면... 각각 별도의 저장공간을 차지하게 됩니다. 이름은 같아도 서로 다른 변수라는 것이죠. 이 둘을 구별하기 위해서는 참조변수 super를 사용해야 합니다. super를 붙이지 않으면... Child클래스의 멤버변수 x를 의미하게 됩니다. 그래서... 오른쪽 코드와 같이 Child인스턴스를 생성한 다음에... method()를 호출하면... x는 Child클래스의 멤버변수 x를 의미하므로 20이 출력되고요. this.x역시 Child클래스의 멤버변수 x를 의미하므로 역시 20이 출력됩니다. super.x는 조상인 Parent로 부터 상속받은 멤버변수 x를 의미하므로 10이 출력됩니다. 왼쪽의 아래에 있는 코드는... 위의 코드와 달리 Child클래스에 멤버변수 x가 없습니다. 나머지는 똑같습니다. 이 때 Child클래스의 인스턴스를 생성해서 method를 호출하면... 변수 x가 하나밖에 없기 때문에 선택의 여지가 없이... 조상으로부터 상속받은 멤버변수 x를 의미합니다. 그래서 10이 출력되고요. this.x역시 상속받은 멤버변수 x를 의미하므로 역시 10이 출력됩니다. super.x는 조상의 멤버변수 x를 의미하므로 10이 출력됩니다. 사실 여기서는 자신의 멤버가 조상의 멤버와 중복되지 않기 때문에... super를 사용할 필요가 없습니다. 상속받은 멤버도 자신의 멤버이므로 this를 사용하는 것만으로도 충분합니다. 단지 참고로... super를 사용했을 때 어떤 결과가 나오는지 보여드리기 위한 것이었습니다. this와 super는 조상의 멤버와 자신의 멤버를 구별하기 위해서 사용된다는 것을 제외하고는 근본적으로 같습니다. this처럼 super도 인스턴스메서드 내에 지역변수로 숨겨진 채로 존재하고요 super에도 인스턴스의 주소가 저장되어 있습니다. 17 17
Java 의 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 2.4 super – 참조변수(2/2) ▶ this – 인스턴스 자신을 가리키는 참조변수. 인스턴스의 주소가 저장되어있음 모든 인스턴스 메서드에 지역변수로 숨겨진 채로 존재 ▶ super – this와 같음. 조상의 멤버와 자신의 멤버를 구별하는 데 사용. 방금 전에는 조상의 멤버변수를 참조하기 위해서 super를 사용했는데요. 조상의 메서드를 참조하는데도 super를 사용합니다. 이전 코드와는 달리 Point3D클래스에서 조상의 메서드에서 오버라이딩할 때, 조상의 메서드를 이용해서 작성하였습니다. super.getLocation()이 조상인 Point클래스의 getLocation()을 호출하는 것입니다. 전에는 주석처리한 부분처럼 되어 있던 코드를... 조상의 메서드를 이용해서 다시 작성한 거죠. 조상에 정의된 getLocation메서드의 내용이... 이 것이므로... 결국 주석처리한 코드와 같은 내용입니다. 그래도... 오버라이딩할 때는... 가능하면... 이처럼... 조상의 메서드를 호출하는 것이 좋습니다. 이렇게 하는 것이 코드의 재사용성을 높이고... 조상코드가 변경되어도 자동적으로 적용되니까요. 사실... 이런 경우에는 굳이 조상의 메서드를 이용할 필요까지는 없었는데요. 예를 들기 위한 것이었으니까... 이해해주시기 바랍니다. ^^; 18 18
Java 2.5 super() – 조상의 생성자(1/3) 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 2.5 super() – 조상의 생성자(1/3) - 자손클래스의 인스턴스를 생성하면, 자손의 멤버와 조상의 멤버가 합쳐진 하나의 인스턴스가 생성된다. - 조상의 멤버들도 초기화되어야 하기 때문에 자손의 생성자의 첫 문장에서 조상의 생성자를 호출해야 한다. 같은 클래스의 다른 생성자를 호출할 때 this를 사용했던 것... 기억하실겁니다. 이와 비슷하게... 조상의 생성자를 호출할 때는 super를 사용합니다. 상속받는 클래스의 인스턴스를 생성하면 조상클래스의 멤버를 포함해서 하나의 인스턴스로 생성됩니다. 이 때, 조상의 멤버들도 초기화되어야 하기 때문에... 조상의 생성자도 호출되어야 합니다. 모든 클래스의 최고 조상인 Object클래스를 제외한 모든 클래스의 생성자의 첫 줄에서는 자신의 생성자 또는 조상의 생성자를 호출해야 합니다. 그렇지 않으면 컴파일러가 자동적으로 조상의 기본 생성자를 호출하는 코드인 super();를 삽입합니다. 이렇게 함으로써... 최고 조상인 Object의 생성자까지 호출되어 올라가서 수행되고... 상속계층도를 따라 내려오면서... 조상들의 생성자가 순서대로 호출됩니다. 그리고 마지막에 자신의 생성자의 두번째 줄부터 수행되는 것이지요. 조상의 생성자를 첫 줄에 호출하도록 하는 것은 자손의 생성자에서 조상의 멤버를 사용할 수 있기 때문에... 자손의 멤버변수보다 조상의 멤버변수들이 먼저 초기화되도록 하기 위한 것입니다. 멤버변수의 초기화는... 각 클래스에서 책임지도록 되어 있습니다. 그래서... 생성자와 초기화 블럭은 상속되지 않고요. 이처럼 자손에서 호출하게 되어 있습니다. 아래의 코드를 보시면... 왼쪽의 Point클래스를 컴파일 하면... 오른쪽과 같이 바뀝니다. Point클래스의 생성자 중에서 두 개의 매개변수를 입력받는 생성자의 첫줄에 생성자 super();를 호출하는 코드가 추가되었습니다. Point클래스가 Object클래스의 자손이니까... 생성자 super는 Object클래스의 생성자를 의미합니다. Point클래스의 기본생성자는 첫번째 줄에서 다른 생성자를 호출하고 있기 때문에... 조상생성자를 호출하는 코드가 추가되지 않았습니다. 결국은 호출한 다른 생성자에서 조상의 생성자가 호출될 것이기 때문이죠. 생성자의 첫 줄에는 항상 생성자를 호출해야한다... 그렇지 않으면 컴파일러가 자동적으로 생성자 super를 추가한다는 것 기억해두시기 바랍니다. 19 19
Java 2.5 super() – 조상의 생성자(2/3) 정석 의 Chapter 7. 객체지향개념 II http://www.javachobo.com 2.5 super() – 조상의 생성자(2/3) 왼쪽과 같이 Point클래스와 이를 조상으로 하는 Point3D클래스가 있을 때... 이와 같이 Point3D인스턴스를 생성하면 어떻게 될까요... 생성자 Point()를 찾을 수 없다는 에러가 발생합니다. 발생한 곳은 Point3D클래스의 생성자이고요... 먼저 Point클래스의 생성자를 보면요... 생성자의 첫줄에 생성자를 호출하고 있지 않습니다. 컴파일 하면 어떻게 바뀔까요? 오른쪽과 같이... 생성자 super()를 호출하는 코드가 자동적으로 추가됩니다. Point클래스는 상속받는 클래스가 없으니까... 자동적으로 Object클래스가 조상이 되고.. 생성자 super는 Object클래스의 생성자를 의미합니다. Point3D클래스의 생성자 역시 첫줄에서 다른 생성자를 호출하지 않기 때문에... 컴파일러가 자동적으로 생성자 super()를 추가해줍니다. Point3D의 조상은 Point클래스이니까... 생성자 super()는 Point클래스의 기본생성자를 의미하겠죠... 그래서... Point3D인스턴스를 생성하면... Point클래스의 기본생성자가 호출되는데... Point클래스를 보시면 알겠지만... 기본생성자가 없습니다. 그래서 Point클래스의 기본생성자가 없다는 에러가 발생하는 것입니다. 이 문제를 해결하는 방법은 두 가지가 있는데요... Point클래스에 기본생성자를 정의해주는 것과 Point3D클래스의 생성자의 첫 줄에 Point클래스의 매개변수가 있는 생성자를 호출하도록 코드를 변경하는 것입니다. 첫번째 해결방법은 생략하고요. 두번째 해결방법으로 코드를 변경하면... 이렇게 됩니다. 이처럼 조상멤버의 초기화는 조상의 생성자를 이용해서 처리하는 것이 바람직합니다. 20 20
Java 2.5 super() – 조상의 생성자(3/3) 정석 * 플래시 동영상 : Super.exe 또는 Super.swf Chapter 7. 객체지향개념 II http://www.javachobo.com 2.5 super() – 조상의 생성자(3/3) * 플래시 동영상 : Super.exe 또는 Super.swf (java_jungsuk_src.zip의 flash폴더에 위치) 방금 전에 살펴본 예제의 실행과정을 플래시 동영상으로 만들어 보았습니다. 메모리 구조의 변화와 실행결과를 설명과 함께 단계별로 자세히 보실 수 있으니까요. 꼭 한번 보시기 바랍니다. 주요부분은 앞서 설명했으니까 혼자 보셔도 별로 어렵지 않으실 겁니다. 21 21
3. package와 import Java 정석 의 Chapter 7. 객체지향개념 II 22 http://www.javachobo.com 3. package와 import 22
Java 3.1 패키지(package) 정석 - 서로 관련된 클래스와 인터페이스의 묶음. Chapter 7. 객체지향개념 II http://www.javachobo.com 3.1 패키지(package) - 서로 관련된 클래스와 인터페이스의 묶음. - 클래스가 물리적으로 클래스파일(*.class)인 것처럼, 패키지는 물리적으로 폴더이다. 패키지는 서브패키지를 가질 수 있으며, ‘.’으로 구분한다. - 클래스의 실제 이름(full name)은 패키지명이 포함된 것이다. (String클래스의 full name은 java.lang.String) - rt.jar는 Java API의 기본 클래스들을 압축한 파일 (JDK설치경로\jre\lib에 위치) 패키지는 한마디로 클래스의 묶음입니다. 서로 관련된 클래스를 그룹지어 놓는 것이지요. 우리가 폴더를 만들어놓고 그 안에 관련된 파일을 모아 놓는 것처럼요... java소스파일을 컴파일하면... 클래스파일이 생기잖아요. 패키지는 폴더가 생성됩니다. 그리고 폴더 안에 폴더를 생성할 수 있는 것처럼 패키지안에 서브패키지를 생성할 수 있습니다. 파일의 실제 이름이 경로를 포함한 이름인 것 처럼... 클래스의 실제 이름은 패키지명이 포함된 것입니다. 예를들어 String클래스의 실제 이름은 java.lang.String입니다. java라는 패키지의 서브패키지인 lang패키지에 속한 String클래스라는 것이죠. JDK를 설치한 폴더의 jre폴더아래 lib폴더를 보시면... rt.jar라는 파일이 있는데... rt는 runtime의 약자이고요. JVM의 실행에 필요한 클래스들을 모아놓은 것입니다. jar파일은 자바에서 사용하는 압축파일인데... zip파일과 압축방식이 같아서 알집이나 winzip으로 압축을 풀 수 있습니다. 아래의 그림은 rt.jar파일의 압축을 푼 것인데요... java폴더 아래 lang이라는 폴더가 있고 그 안에 String이라는 클래스파일이 있는 것을 알 수 있습니다. System클래스파일도 있고요... 패키지는 관련된 클래스의 묶음이라는 것과 패키지와 클래스파일은 폴더와 파일의 관계다...라는 것... 어렵지 않게 이해하셨을 겁니다. 23 23
Java 3.2 패키지의 선언 정석 - 패키지는 소스파일에 첫 번째 문장(주석 제외)으로 단 한번 선언한다. Chapter 7. 객체지향개념 II http://www.javachobo.com 3.2 패키지의 선언 - 패키지는 소스파일에 첫 번째 문장(주석 제외)으로 단 한번 선언한다. - 하나의 소스파일에 둘 이상의 클래스가 포함된 경우, 모두 같은 패키지에 속하게 된다.(하나의 소스파일에 단 하나의 public클래스만 허용한다.) - 모든 클래스는 하나의 패키지에 속하며, 패키지가 선언되지 않은 클래스는 자동적으로 이름없는(unnamed) 패키지에 속하게 된다. 패키지는 키워드 package를 사용해서... 소스파일의 첫 번째 문장에 단 한번만 선언할 수 있습니다. 그리고 이 소스파일에 선언된 클래스는 모두 같은 패키지에 속하게 됩니다. 왼쪽의 코드에 보면... PackageTest.java라는 소스파일에... 주석을 제외한 첫번째 문장에 패키지를 선언하였고요. 그 아래에 두 개의 클래스 PackageTest와 PackageTest2가 선언되어 있는데요. 이 두 클래스 모두 com.javachobo.book이라는 패키지에 속하게 됩니다. 이처럼 하나의 소스파일에 둘 이상의 클래스를 선언하는 경우에는 단 하나의 public클래스만 선언할 수 있습니다. 그래서 PakcageTest2에는 public을 붙일 수 없고요... 또 한가지 지켜야할 규칙은 소스파일의 이름은 public클래스의 이름과 일치해야한다는 것입니다. 그래서 소스파일의 이름이 public클래스의 이름인... PackageTest.java로 했습니다. 만일 두 클래스 모두 public을 붙여야 한다면... 각각 다른 소스파일에 작성해야 합니다. 둘 다 public이 안붙어 있다면... 소스파일의 이름은 둘 중의 어느쪽 클래스의 이름으로 해도 괜찮습니다. public은 접근제어자인데요... 다음 강의에서 자세히 배우게 됩니다. 지금은 일단 그런 규칙이 있다는 것만 알아두시기 바랍니다. javac의 d옵션을 사용하면 소스파일에 선언된 패키지구조를 지정된 경로에 자동적으로 생성해줍니다. 여기서는 현재폴더를 의미하는 점을 경로로 지정해주어 컴파일 하였습니다. 그러니까... 오른쪽과 같이... 현재폴더인 work아래에 패키지 구조에 맞게 폴더들이 자동적으로 생성되고... 그 안에 PackageTest클래스파일이 생성되었습니다. 만일 d옵션을 사용하지 않고 컴파일하면... 클래스파일만 생성되고... 패키지폴더들은 생성되지 않기 때문에 직접 만들어 주어야 합니다. 모든 클래스는 반드시 하나의 패키지에 속해야 합니다. 그런데도 지금까지... 패키지를 지정하지 않고도 문제가 없었던 것은... 패키지를 지정하지 않으면... 자동적으로 이름없는 패키지에 속하게 되기 때문입니다. 그렇게 함으로써 모든 클래스는 반드시 하나의 패키지에 속해야 한다는 원칙을 지키게 되는 것이죠. 그래서 패키지를 지정하지 않은 클래스들은 모두 같은 패키지에 속하게 되겠죠. 24 24
3.3 클래스패스(classpath) 설정(1/2) Java 의 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 3.3 클래스패스(classpath) 설정(1/2) - 클래스패스(classpath)는 클래스파일(*.class)를 찾는 경로. 구분자는 ‘;’ - 클래스패스에 패키지가 포함된 폴더나 jar파일을(*.jar) 나열한다. - 클래스패스가 없으면 자동적으로 현재 폴더가 포함되지만 클래스패스를 지정할 때는 현재 폴더(.)도 함께 추가해주어야 한다. 클래스패스는 클래스파일을 찾는 경로이고요... 각 경로간의 구분은 ‘;’으로 합니다. 경로가 여러 개 있을 때는 클래스 파일을 찾을 때 제일 왼쪽의 경로부터 순서대로 찾아나가기 시작합니다. 지금까지는 클래스패스를 지정하지 않고도... 실행할 수 있었는데요... 그 이유는 현재 폴더가 자동적으로 클래스패스에 포함되기 때문이었습니다. 만일 클래스패스를 지정해야 한다면... 반드시 현재폴더를 의미하는 ‘.’을 클래스 패스에 추가해주어야 합니다. 현재폴더는 클래스패스의 기본값인데... 변경을 하면... 기본값은 더이상 사용되지 않기 때문이죠. 방금 전에 컴파일한 PackageTest클래스는 c:\jdk1.5\work폴더 아래에 있기 때문에... c:\jdk1.5\work폴더를 클래스패스에 지정해주어야만... PackageTest클래스를 찾을 수 있습니다. JDK의 설치및 설정에 대한 강좌에서 설명드렸기 때문에... 클래스패스를 설정하는 방법을 여기서 또 다루지는 않겠습니다. 실행할 때는 이처럼... 클래스앞에 패키지명을 다 붙여줘야 한다는 것과... cp옵션을 사용해서 일시적으로 클래스패스를 지정해주는 방법도 있다는 것... 참고로 알아두세요. [참고] java.exe의‘cp’옵션을 이용해서 일시적으로 클래스패스를 지정해 줄 수도 있다. 25 25
3.3 클래스패스(classpath) 설정(2/2) Java 의 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 3.3 클래스패스(classpath) 설정(2/2) ▶ 클래스패스로 자동 포함된 폴더 for 클래스파일(*.class) : 수동생성 해야함. - JDK설치경로\jre\classes ▶ 클래스패스로 자동 포함된 폴더 for jar파일(*.jar) : JDK설치시 자동생성됨. - JDK설치경로\jre\lib\ext JDK1.2에서부터.... 클래스패스를 설정하지 않아도 되도록... 두 개의 폴더를 지정해 놓았습니다. JDK설치폴더 아래 jre아래 classes폴더와 jre아래 lib아래 ext폴더 입니다. ext폴더는 JDK를 설치할때 자동생성되지만... classes폴더는 자동생성되지 않기 때문에... 직접 만들어줘야 하고요. 클래스 파일은 classes폴더에, jar파일은 ext폴더에 넣기만 하면 됩니다. 26 26
Java 3.4 import문 정석 - 사용할 클래스가 속한 패키지를 지정하는데 사용. 의 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 3.4 import문 - 사용할 클래스가 속한 패키지를 지정하는데 사용. - import문을 사용하면 클래스를 사용할 때 패키지명을 생략할 수 있다. - java.lang패키지의 클래스는 import하지 않고도 사용할 수 있다. String, Object, System, Thread ... import문은 사용할 클래스의 패키지를 지정하는데 사용합니다. 다른 패키지의 클래스를 사용하려면... 클래스의 패키지명도 같이 적어줘야하는데... import문으로 한번만 패키지를 선언해주면... 해당 패키지의 클래스는 패키지명을 적어주지 않아도 됩니다. 예를 들어 java.util패키지의 Date클래스를 사용하려면... 아래와 같이... 클래스 이름앞에 패키지명을 붙여줘야하는데... import문을 이용해서 java.util패키지를 선언하면... 이 패키지에 속한 클래스들은 패키지명을 붙이지 않고 편하게 사용할 수 있습니다. 예외적으로 java.lang패키지의 클래스들은 다른 패키지에 속한 클래스인데도 import하지 않고 클래스 이름만으로 사용할 수 있는데요. 그 이유는 매우 빈번하게 사용되는 패키지라서... 매번 import문을 쓰는 것이 불편하니까... 생략할 수 있도록 하였기 때문입니다. 대표적인 java.lang패키지의 클래스로는 String, Object, System, Thread클래스 등이 있고요. 원래는 아래와 같이 import문을 써주어야하지만... 생략할 수 있습니다. 컴파일러는 import문의 정보를 이용해서 클래스이름을 패키지를 포함한 것으로 변환합니다. 이 코드를 컴파일 하면... 이와 같이 바뀌겠죠... 27 27
Java 3.5 import문의 선언 정석 - import문은 패키지문과 클래스선언의 사이에 선언한다. Chapter 7. 객체지향개념 II http://www.javachobo.com 3.5 import문의 선언 - import문은 패키지문과 클래스선언의 사이에 선언한다. - import문을 선언하는 방법은 다음과 같다. import문은 패키지문과 클래스 선언 사이에 위치해야 하고요... package문과는 달리 import문은 여러 번 사용할 수 있습니다. 특정 패키지의 모든 클래스를 import할 때는 패키지명 다음에 별표‘*’를 적어주면 되고요. 특정 클래스 하나만을 import할 때는 패키지명과 클래스명을 적어주면 됩니다. 첫번째 import문은 java.text패키지의 SimpleDateFormat클래스 하나만을 import한 것이고... 두번째 import문은 java.util패키지의 모든 클래스를 import한 것입니다. 그래서 java.util패키지에 속한 Date클래스를 이렇게 패키지 이름없이 클래스 이름만으로 사용할 수 있는 것입니다. 28 28
Java 3.5 import문의 선언 - 선언예 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 3.5 import문의 선언 - 선언예 - import문은 컴파일 시에 처리되므로 프로그램의 성능에 아무런 영향을 미치지 않는다. - 다음의 두 코드는 서로 의미가 다르다. - 이름이 같은 클래스가 속한 두 패키지를 import할 때는 클래스 앞에 패키지명을 붙여줘야 한다. import문은 컴파일 할 때 처리되는 문장이기 때문에 import문은 프로그램의 성능에 아무런 영향을 주지 않기 때문에 import문을 많이 사용한다던가... 클래스이름대신 별표를 사용한다고 해서 프로그램의 성능을 떨어뜨리지 않습니다. 그래서... import할 클래스의 이름을 일일이 적어주는 것보다... 편하게 별표를 사용하는 것이 좋습니다. 그러나... 이 왼쪽의 코드를 오른쪽과 같이 할 수 없다는 것... 주의하시기 바랍니다. import문은 지정된 패키지에 포함된 클래스들만을 import할 수 있지... 서브패키지에 속하는 클래스들 까지 import하지는 못합니다. 또 한가지 주의할 점은... import한 패키지들 간의 충돌문제 인데요... 아래와 같이 두 개의 패키지를 import했는데... 두 패키지에 같은 이름의 클래스가 있는 경우에는... 이 클래스를 사용할 때 패키지명을 붙여줘서 어느 패키지의 클래스인지... 구분할 수 있게 해야 합니다. 보통은 편하게 별표를 사용하면 되지만... 예를 들어 프로젝트에서 사용되는 공통라이브러리를 작성하는 경우에는 import문에 패키지명과 클래스명을 같이 적어줌으로써 사용한 클래스가 어떤 패키지에 속한 것인지 정확히 명시해주는 것이 필요할 때가 있습니다. 그러면 import문만 보고도 이 소스코드에 어떤 클래스들을 사용되었는지 쉽게 알 수 있습니다. 29 29
감사합니다. http://www.javachobo.com Java 정석 의 정석 Chapter 7. 객체지향개념 II http://www.javachobo.com 감사합니다. 더 많은 동영상강좌를 아래의 사이트에서 구하실 수 있습니다. http://www.javachobo.com 이것으로 제 7장 객체지향개념II-1에 대한 강의를 모두 마치겠습니다. 감사합니다. 이 동영상강좌는 비상업적 용도일 경우에 한해서 저자의 허가없이 배포하실 수 있습니다. 그러나 일부 무단전제 및 변경은 금지합니다. 관련문의 : 남궁성 castello@naver.com