[Chapter 7] 객제지향 프로그래밍 2_1
'자바의 정석 3rd Editon'을 공부하며 정리한 내용입니다.
1. 상속(inheritance)
1. 상속의 정의와 장점
- 상속: 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것
- 상속을 통해 클래스를 작성하면 적은 양의 코드로 새러은 클래스를 작성할 수 있고 코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 변경이 매우 용이
- 코드의 재사용성을 높이고 코드의 중복을 제거해 프로그램의 생산성과 유지보수에 기여
자바에서 상속을 구현하는 방법
- 새로 작성하고자 하는 클래스의 이름 뒤에 상속받고자 하는 클래스의 이름을 키워드
extends
와 함께 써주면 됨
class Child extends Parent {
// ...
}
- 조상 클래스 부모(parent) 클래스, 상위(super) 클래스, 기반(base) 클래스
- 자손 클래스 자식(child) 클래스, 하위(sub) 클래스, 파생된(derived) 클래스
-
자손 클래스는 조상 클래스의 모든 멤버를 상속 받음
- Parent 클래스에 age라는 정수형 변수를 멤버변수로 추가하면, 자손 클래스는 조상의 멤버를 모두 상속받기 ㄸ문에, Child 클래스는 자동적으로 age라는 멤버변수가 추가된 것 같은 효과를 얻음
-
조상 클래스가 변경되면 자손 클래스는 자동적으로 영향을 받지만, 자손 클래스가 변경되는 것은 조상 클래스에 아무런 영향을 주지 않음
-
자손 클래스는 조상 클래스의 모든 멤버를 상속 받으므로 항상 조상 클래스보다 같거나 많은 멤버를 가짐. 상속에 상속을 거듭할수록 상속받는 클래스의 멤버 개수는 점점 늘어나게 됨
- 생성자와 초기화 블럭은 상속되지 않음. 멤버만 상속됨
- 자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많음
- 같은 내용의 코드를 하나 이상의 클래스에 중복적으로 추가해야하는 경우에는 상속관계를 이용해 코드의 중복을 최소화해야 함
- 조상 클래스만 변경해도 모든 자손 클래스에, 자손의 자손 클래스에까지 영향을 미치기 때문에, 클래스간의 상속관계를 맺어 주면 자손 클래스들의 공통적인 부분은 조상 클래스에서 관리하고 자손 클래스는 자신에 정의된 멤버들만 관리하면 되므로 각 클래스의 코드가 적어져 관리가 쉬워짐
자손 클래스의 인스턴스를 생성하면 조상 클래스의 멤버와 자손 클래스의 멤버가 합쳐진 하나의 인스턴스로 생성됨
1.2 클래스간의 관계 - 포함관계
- 클래스 간에 포함(Composite) 관계를 맺어주면 클래스를 재사용하는 것이 가능
- 클래스 간의 포함관계를 맺어주는 것은 한 클래스의 멤버변수로 다른 클래스 타입의 참조변수를 선언하는 것을 의미
// Circle class
class Circle {
int x; // x좌표
int y; // y좌표
int r; // 반지름
}
// Point class
class Point {
int x; // x좌표
int y; // y좌표
}
// Point 클래스를 재사용해서 Circle 클래스 작성
class Circle {
Point c = new Point(); // 원점
int r;
}
- 하나의 거대한 클래스를 작성하는 것보다 단위별로 여러 개의 클래스를 작성한 다음 이 단위 클래스들을 포함관계로 재사용하면 보다 간결하고 쉽게 클래스를 작성할 수 있음
- 작성된 단위 클래스들은 다른 클래스를 작성하는데 재사용될 수 있음
1.3 클래스간의 관계 결정하기
- 상속관계를 맺어줄 것인지 포함관계를 맺어 줄 것인지 결정하는 것이 혼돈스러울 경우, '~은 ~이다(is-a)'와 '~은 ~을 가지고 있다(has-a)'를 넣어서 문장을 만들어보면 클래스 간의 관계가 명확해짐
- 원(Circle)은 점(Point)이다 - Circle is a Point
- 원(Circle)은 점(Point)을 가지고 있다 - Circle has a Point
- 원은 원점(Point)과 반지름으로 구성되므로 위의 두 문장을 비교해보면 두 번째 문장이 더 옳다는 것을 알 수 있음
- '~은 ~이다'라는 문장이 성립한다면 상속 관계를, '~은 ~을 가지고 있다'는 문장이 성립한다면 포함관계를 맺어주면 됨
1.4 단일 상속(single inheritance)
- 다른 객체지향언어인 C++에서는 여러 조상 클래스로부터 상속받는 것이 가능한 '다중상속(multiple inheritance)'을 허용하지만 자바에서는 오직 단일 상속만 허용
- 둘 이상의 클래스로부터 상속을 받을 수 없음
- 다중상속 장점: 여러 클래스로부터 상속받을 수 있기 때문에 복합적인 기능을 가진 클래스를 쉽게 작성할 수 있음
- 다중상속 단점: 클래스간의 관계가 매우 복잡해진다는 것과 서로 다른 클래스로부터 상속받은 멤버간의 이름이 같은 경우 구별할 수 있는 방법이 없다는 단점을 가짐
- 다닝ㄹ 상속이 하나의 조상 클래스만을 가질 수 있기 때문에 다중상속에 비해 불편한 점도 있지만, 클래스 간의 관계가 명확해지고 코드를 더욱 신뢰할 수 있게 만들어준다는 점에서 다중상속보다 유리
class Tv {
boolean power; // 전원상태(on/off)
int channel; // 채널
void power() { power = !power; }
void channelUp() { ++channel; }
void channelDown() { --channel; }
}
class VCR {
boolean power; // 전원상태(on/off)
int counter = 0;
void power() { power = !power; }
void play() { /* 내용생략*/ }
void stop() { /* 내용생략*/ }
void rew() { /* 내용생략*/ }
void ff() { /* 내용생략*/ }
}
class TVCR extends Tv {
VCR vcr = new VCR();
int counter = vcr.counter;
void play() {
vcr.play();
}
void stop() {
vcr.stop();
}
void rew() {
vcr.rew();
}
void ff() {
vcr.ff();
}
}
- 자바는 다중상속을 허용하지 않으므로 Tv 클래스를 조상으로 하고, VCR 클래스는 TVCR 클래스에 포함시킴
- TVCR 클래스에 VCR 클래스의 메서드와 일치하는 선언부를 가진 ㅁ메서드를 선언하고 내용은 VCR 클래스의 것을 호출해서 사용하도록 함
- 외부적으로는 TVCR 클래스의 인스턴스를 사용하는 것처럼 보이지만 내부적으로는 VCR 클래스의 인스턴스를 생성해서 사용하는 것
- 이렇게 함으로써 VCR 클래스의 메서드의 내용이 변경되더라도 TVCR 클래스의 메서드들 역시 변경된 내용이 적용되는 결과를 얻을 수 있음
1.5 Object 클래스 - 모든 클래스의 조상
- Object 클래스는 모든 클래스 상속계층도의 최상위에 있는 조상 클래스
- 다른 클래스로부터 상속 받지 않는 모든 클래스들은 자동적으로 Object 클래스로부터 상속받게 함
- 만일 다른 클래스로부터 상속을 받는다고 하더라도 상속계층도를 따라 조상클래스, 조상클래스의 조상클래스를 찾아 올라가다 보면 결국 마지막 최상위 조상은 Object 클래스일 것
- Object 클래스에는
toString()
, equals()
와 같은 모든 인스턴스가 가져야 할 기본적인 11개의 메서드가 정의되어 있음 => 9장 참고
2. 오버라이딩(overriding)
2.1 오버라이딩이란?
- 오바라이딩: 조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것
- 상속받은 메서드를 그대로 사용하기도 하지만, 자손 클래스 자신에 맞게 변경해야하는 경우가 많은데 이럴 때 조상의 메서드를 오버라이딩함
2.2 오버라이딩의 조건
- 오버라이딩은 메서드의 내용만을 새로 작성하는 것이므로 메서드의 선언부는 조상의 것과 완전히 일치해야 함
자손 클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와
- 이름이 같아야 함
- 매개변수가 같아야 함
- 반환타입이 같아야 함
- 접근 제어자(access modifier)와 예외(exception)은 제한된 조건 하에서만 다르게 변경 가능
1. 접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없음
2. 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없음
3. 인스턴스메서드를 static 메서드로 또는 그 반대로 변경할 수 없음
- 조상 클래스에 정의된 static 메서드를 자손 클래스에서 똑같은 이름의 static 메서드로 정의할 수 있나요?
정의할 수 있음. 하지만 각 클래스에 별개의 static 메서드를 정의한 것일 뿐 오버라이딩이 아님. 각 메서드는 클래스 이름으로 구별될 수 있으며, 호출할 때눈 참조변수.메서드이름()
대신 클래스이름.메서드이름()
으로 하는 것이 바람직. static 멤버들은 자신들이 정의된 클래스에 묶여있다고 생각할 것
2.3 오버로딩 vs. 오버라이딩
오버로딩(overloading) 기존에 없는 새로운 메서드를 정의하는 것(new)
오버라이딩(overriding) 상속받은 메서드의 내용을 변경하는 것(change, modify)
2.4 super
- super: 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조 변수
- 멤버변수와 지역변수의 이름이 같을 때 this를 붙여서 구별했듯이 상속받은 멤버와 자신의 멤버와 이름이 같을 때는 super를 붙여서 구분
- 조상 클래스로부터 상속받은 멤버도 자손 클래스 자신의 멤버이므로 super 대신 this 사용 가능
- 조상 클래스의 멤버와 자손 클래스의 멤버가 중복 정의되어 서로 구별해야하는 경우에만 super를 사용하는 것이 좋음
- 조상의 멤버와 자신의 멤버를 구별하는데 사용된다는 점을 제외하고는 super와 this는 근본적으로 같음
- 모든 인스턴스 메서드에는 자신이 속한 인스턴스의 주소가 지역변수로 저장되는데, 이것이 참조변수인 this와 super의 값이 됨
- 조상 클래스에 선언된 멤버변수와 같은 이름의 멤버변수를 자손 클래스에서 중복해서 정의하는 것이 가능하며 참조변수 super를 이용해서 서로 구별 가능
- 메서드도 super를 써서 호출 가능. 조상 클래스의 메서드를 자손 클래스에서 오버라이딩한 경우에 super를 사용
class Point {
int x;
int y;
String getLocation() {
return "x :" + x + ", y :" + y;
}
}
class Point3D extends Point() {
int z;
String getLocation() {
// return "x :" + x + ", y :" + y + ", z :" + z;
return super.getLocation() + ", z :" + z;
}
}
-
조상 클래스의 메서드의 내용에 추가적으로 작업을 덧붙이는 경우라면 super를 사용해 조상 클래스의 메서드를 포함시키는 것이 좋음
- 후에 조상 클래스의 메서드가 변경되더라도 변경된 내용이 자손 클래스의 메서드에 자동적으로 반영될 것이기 때문
-
static 메서드(클래스 메서드)는 인스턴스와 관련이 없음
- this와 마찬가지로 super 역시 static 메서드에서는 사용할 수 없고 인스턴스 메서드에서만 사용 가능
2.5 super() - 조상 클래스의 생성자
this()
는 같은 클래스의 다른 생성자를 호출하는 데 사용되지만, super()
는 조상 클래스의 생성자를 호출하는데 사용
- 자손 클래스의 인스턴스를 생성하면 자손의 멤버와 조상의 멤버가 모두 합쳐진 하나의 인스턴스가 생성됨
- 이 때 조상 클래스 멤버의 초기화 작업이 수행되어야 하기 때문에 자손 클래스의 생성자에서 조상 클래스의 생성자가 호출되어야 함
- 생성자의 첫 줄에서 조상 클래스의 생성자를 호출해야하는 이유는 자손 클래스의 멤버가 조상 클래스의 멤버를 사용할 수도 있으므로 조상의 멤버들이 먼저 초기화되어 있어야 하기 때문
- 조상 클래스 생성저의 호출은 클래스의 상속관계를 거술러 올라가면서 계속 반복되며 마지막으로 모든 클래스의 최고 조상인 Object 클래스의 생성자인 Object()까지 가서야 끝이 남
Object 클래스를 제외한 모든 클래스의 생성자 첫 줄에 생성자 this()
또는 super()
를 호출해야 함. 그렇지 않으면 컴파일러가 자동적으로 super()
를 생성자의 첫 줄에 삽입
- 인스턴스를 생성할 때 클래스를 선택하는 것만큼 생성자를 선택하는 것도 중요
- 클래스 - 어떤 클래스의 인스턴스를 생성할 것인가?
- 생성자 - 선택한 클래스의 어떤 생성자를 이용해서 인스턴스를 생성할 것인가?
- 조상 클래스의 멤버변수는 조상의 생성자에 의해 초기화되도록 해야 함
3. package와 import
3.1 패키지(package)
- 패키지: 클래스의 묶음
- 패키지에는 클래스 또는 인터페이스를 포함시킬 수 있음
- 서로 관련된 클래스들끼리 그룹 단위로 묶어 놓음으로써 클래스를 효율적으로 관리할 수 있음
- 같은 이름의 클래스라도 서로 다른 패키지에 존재하는 것이 가능하므로, 자신만의 패키지 체계를 유지함으로써 다른 개발자가 개발한 클래스 라이브러리의 클래스와 이름이 충돌하는 것을 피할 수 있음
- 클래스가 물리적으로 하나의 클래스파일(.class)인 것과 같이 패키지는 물리적으로 하나의 디렉토리
- 패키지도 다른 패키지를 포함할 수 있으며 점'.'으로 구분
- 하나의 소스파일에는 첫 번째 문장으로 단 한 번의 패키지 선언만을 허용
- 모든 클래스는 반드시 하나의 패키지에 속해야 함
- 패키지는 점(.)을 구분자로 하여 계층구조로 구성할 수 있음
- 패키지는 물리적으로 클래스 파일(.class)을 포함하는 하나의 디렉토리
3.2 패키지의 선언
package 패키지명;
- 클래스나 인터페이스의 소스파일(.java)의 맨 위에 한 줄만 적어주면 됨
- 패키지 선언문은 반드시 소스파일에서 주석과 공백을 제회한 첫 번째 문장잉야 하며, 하나의 소스파일에 단 한 번만 선언될 수 있음
- 해당 소스파일에 포함된 모든 클래스나 인터페이스는 선언된 패키지에 속하게 됨
- 패키지명은 대소문자를 모두 허용하지만, 클래스명과 쉽게 구분하기 위해서 소문자로 하는 것을 원칙으로 함
- 소스파일에 자신이 속할 패키지를 지정하지 않은 클래스는 자동적으로 '이름 없는 패키지'에 속하게 됨. 패키지를 지정하지 않는 모든 클래스들은 같은 패키지에 속하게 됨
- 큰 프로젝트나 Java API와 같은 클래스 라이브러리를 작성하는 경우에는 미리 패키지를 구성하여 적용
3.3 import 문
- 클래스의 코드를 작성하기 전에 import문으로 사용하고자 하는 클래스의 패키지를 미리 명시해주면 소스코드에 사용되는 클래스이름에서 패키지명은 생략할 수 있음
- import문의 역할: 컴파일러에게 소스파일에 사용된 클래스의 패키지에 대한 정보를 제공하는 것
- 컴파일 시 컴파일러는 import문을 통해 소스파일에 사용된 클래스들의 패키지를 알아 낸 다음, 모든 클래스 이름 앞에 패키지명을 붙여줌
이클립스는 단축키 ctrl + shift + o
를 누르면, 자동으로 import문을 추가해줌
3.4 import문의 선언
소스파일(*.java)의 구성
1. package문
2. import문
3. 클래스 선언
import문 선언 방법
import 패키지명.클랫스명;
or
import 패키지명.*;
- 같은 패키지에서 여러 개의 클래스가 사용될 때, import문을 여러 번 사용하는 대신
패키지명.*
을 이요해서 지정된 패키지에 속한 모든 클래스를 패키지명 없이 사용할 수 있음
java.lang
패키지는 매우 빈번히 사용되는 중요한 클래스들이 속한 패키지이기 때문에 따로 import문을 지정하지 않아도 됨
3.5 static import문
- static import문을 사용하면 static멤버를 호출할 때 클래스 이름을 생략할 수 있음
- 특정 클래스의 static 멤버를 자주 사용할 때 편리
import static java.lang.Integer.*; // Integer 클래스의 모든 static 메서드
import static java.lang.Math.random; // Math.random()만. 괄호 안 붙임
import static java.lang.System.out; // System.out을 out만으로 참조 가능
System.out.println(Math.random()) -> out.println(random())
Author And Source
이 문제에 관하여([Chapter 7] 객제지향 프로그래밍 2_1), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@slchoi/Chapter-7-객제지향-프로그래밍-21
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
자바에서 상속을 구현하는 방법
- 새로 작성하고자 하는 클래스의 이름 뒤에 상속받고자 하는 클래스의 이름을 키워드
extends
와 함께 써주면 됨
class Child extends Parent {
// ...
}
- 조상 클래스 부모(parent) 클래스, 상위(super) 클래스, 기반(base) 클래스
- 자손 클래스 자식(child) 클래스, 하위(sub) 클래스, 파생된(derived) 클래스
자손 클래스는 조상 클래스의 모든 멤버를 상속 받음
- Parent 클래스에 age라는 정수형 변수를 멤버변수로 추가하면, 자손 클래스는 조상의 멤버를 모두 상속받기 ㄸ문에, Child 클래스는 자동적으로 age라는 멤버변수가 추가된 것 같은 효과를 얻음
조상 클래스가 변경되면 자손 클래스는 자동적으로 영향을 받지만, 자손 클래스가 변경되는 것은 조상 클래스에 아무런 영향을 주지 않음
자손 클래스는 조상 클래스의 모든 멤버를 상속 받으므로 항상 조상 클래스보다 같거나 많은 멤버를 가짐. 상속에 상속을 거듭할수록 상속받는 클래스의 멤버 개수는 점점 늘어나게 됨
- 생성자와 초기화 블럭은 상속되지 않음. 멤버만 상속됨
- 자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많음
자손 클래스의 인스턴스를 생성하면 조상 클래스의 멤버와 자손 클래스의 멤버가 합쳐진 하나의 인스턴스로 생성됨
// Circle class
class Circle {
int x; // x좌표
int y; // y좌표
int r; // 반지름
}
// Point class
class Point {
int x; // x좌표
int y; // y좌표
}
// Point 클래스를 재사용해서 Circle 클래스 작성
class Circle {
Point c = new Point(); // 원점
int r;
}
- 원(Circle)은 점(Point)이다 - Circle is a Point
- 원(Circle)은 점(Point)을 가지고 있다 - Circle has a Point
- 원은 원점(Point)과 반지름으로 구성되므로 위의 두 문장을 비교해보면 두 번째 문장이 더 옳다는 것을 알 수 있음
- 둘 이상의 클래스로부터 상속을 받을 수 없음
- 다중상속 장점: 여러 클래스로부터 상속받을 수 있기 때문에 복합적인 기능을 가진 클래스를 쉽게 작성할 수 있음
- 다중상속 단점: 클래스간의 관계가 매우 복잡해진다는 것과 서로 다른 클래스로부터 상속받은 멤버간의 이름이 같은 경우 구별할 수 있는 방법이 없다는 단점을 가짐
class Tv {
boolean power; // 전원상태(on/off)
int channel; // 채널
void power() { power = !power; }
void channelUp() { ++channel; }
void channelDown() { --channel; }
}
class VCR {
boolean power; // 전원상태(on/off)
int counter = 0;
void power() { power = !power; }
void play() { /* 내용생략*/ }
void stop() { /* 내용생략*/ }
void rew() { /* 내용생략*/ }
void ff() { /* 내용생략*/ }
}
class TVCR extends Tv {
VCR vcr = new VCR();
int counter = vcr.counter;
void play() {
vcr.play();
}
void stop() {
vcr.stop();
}
void rew() {
vcr.rew();
}
void ff() {
vcr.ff();
}
}
- TVCR 클래스에 VCR 클래스의 메서드와 일치하는 선언부를 가진 ㅁ메서드를 선언하고 내용은 VCR 클래스의 것을 호출해서 사용하도록 함
- 외부적으로는 TVCR 클래스의 인스턴스를 사용하는 것처럼 보이지만 내부적으로는 VCR 클래스의 인스턴스를 생성해서 사용하는 것
toString()
, equals()
와 같은 모든 인스턴스가 가져야 할 기본적인 11개의 메서드가 정의되어 있음 => 9장 참고2.1 오버라이딩이란?
- 오바라이딩: 조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것
- 상속받은 메서드를 그대로 사용하기도 하지만, 자손 클래스 자신에 맞게 변경해야하는 경우가 많은데 이럴 때 조상의 메서드를 오버라이딩함
2.2 오버라이딩의 조건
- 오버라이딩은 메서드의 내용만을 새로 작성하는 것이므로 메서드의 선언부는 조상의 것과 완전히 일치해야 함
자손 클래스에서 오버라이딩하는 메서드는 조상 클래스의 메서드와
- 이름이 같아야 함
- 매개변수가 같아야 함
- 반환타입이 같아야 함
- 접근 제어자(access modifier)와 예외(exception)은 제한된 조건 하에서만 다르게 변경 가능
1. 접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없음
2. 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없음
3. 인스턴스메서드를 static 메서드로 또는 그 반대로 변경할 수 없음
- 조상 클래스에 정의된 static 메서드를 자손 클래스에서 똑같은 이름의 static 메서드로 정의할 수 있나요?
정의할 수 있음. 하지만 각 클래스에 별개의 static 메서드를 정의한 것일 뿐 오버라이딩이 아님. 각 메서드는 클래스 이름으로 구별될 수 있으며, 호출할 때눈참조변수.메서드이름()
대신클래스이름.메서드이름()
으로 하는 것이 바람직. static 멤버들은 자신들이 정의된 클래스에 묶여있다고 생각할 것
2.3 오버로딩 vs. 오버라이딩
오버로딩(overloading) 기존에 없는 새로운 메서드를 정의하는 것(new)
오버라이딩(overriding) 상속받은 메서드의 내용을 변경하는 것(change, modify)
2.4 super
- super: 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조 변수
- 멤버변수와 지역변수의 이름이 같을 때 this를 붙여서 구별했듯이 상속받은 멤버와 자신의 멤버와 이름이 같을 때는 super를 붙여서 구분
- 조상 클래스로부터 상속받은 멤버도 자손 클래스 자신의 멤버이므로 super 대신 this 사용 가능
- 조상 클래스의 멤버와 자손 클래스의 멤버가 중복 정의되어 서로 구별해야하는 경우에만 super를 사용하는 것이 좋음
- 조상의 멤버와 자신의 멤버를 구별하는데 사용된다는 점을 제외하고는 super와 this는 근본적으로 같음
- 모든 인스턴스 메서드에는 자신이 속한 인스턴스의 주소가 지역변수로 저장되는데, 이것이 참조변수인 this와 super의 값이 됨
- 조상 클래스에 선언된 멤버변수와 같은 이름의 멤버변수를 자손 클래스에서 중복해서 정의하는 것이 가능하며 참조변수 super를 이용해서 서로 구별 가능
- 메서드도 super를 써서 호출 가능. 조상 클래스의 메서드를 자손 클래스에서 오버라이딩한 경우에 super를 사용
class Point {
int x;
int y;
String getLocation() {
return "x :" + x + ", y :" + y;
}
}
class Point3D extends Point() {
int z;
String getLocation() {
// return "x :" + x + ", y :" + y + ", z :" + z;
return super.getLocation() + ", z :" + z;
}
}
-
조상 클래스의 메서드의 내용에 추가적으로 작업을 덧붙이는 경우라면 super를 사용해 조상 클래스의 메서드를 포함시키는 것이 좋음
- 후에 조상 클래스의 메서드가 변경되더라도 변경된 내용이 자손 클래스의 메서드에 자동적으로 반영될 것이기 때문
-
static 메서드(클래스 메서드)는 인스턴스와 관련이 없음
- this와 마찬가지로 super 역시 static 메서드에서는 사용할 수 없고 인스턴스 메서드에서만 사용 가능
2.5 super() - 조상 클래스의 생성자
this()
는 같은 클래스의 다른 생성자를 호출하는 데 사용되지만,super()
는 조상 클래스의 생성자를 호출하는데 사용- 자손 클래스의 인스턴스를 생성하면 자손의 멤버와 조상의 멤버가 모두 합쳐진 하나의 인스턴스가 생성됨
- 이 때 조상 클래스 멤버의 초기화 작업이 수행되어야 하기 때문에 자손 클래스의 생성자에서 조상 클래스의 생성자가 호출되어야 함
- 생성자의 첫 줄에서 조상 클래스의 생성자를 호출해야하는 이유는 자손 클래스의 멤버가 조상 클래스의 멤버를 사용할 수도 있으므로 조상의 멤버들이 먼저 초기화되어 있어야 하기 때문
- 조상 클래스 생성저의 호출은 클래스의 상속관계를 거술러 올라가면서 계속 반복되며 마지막으로 모든 클래스의 최고 조상인 Object 클래스의 생성자인 Object()까지 가서야 끝이 남
Object 클래스를 제외한 모든 클래스의 생성자 첫 줄에 생성자
this()
또는super()
를 호출해야 함. 그렇지 않으면 컴파일러가 자동적으로super()
를 생성자의 첫 줄에 삽입
- 인스턴스를 생성할 때 클래스를 선택하는 것만큼 생성자를 선택하는 것도 중요
- 클래스 - 어떤 클래스의 인스턴스를 생성할 것인가?
- 생성자 - 선택한 클래스의 어떤 생성자를 이용해서 인스턴스를 생성할 것인가?
- 조상 클래스의 멤버변수는 조상의 생성자에 의해 초기화되도록 해야 함
3. package와 import
3.1 패키지(package)
- 패키지: 클래스의 묶음
- 패키지에는 클래스 또는 인터페이스를 포함시킬 수 있음
- 서로 관련된 클래스들끼리 그룹 단위로 묶어 놓음으로써 클래스를 효율적으로 관리할 수 있음
- 같은 이름의 클래스라도 서로 다른 패키지에 존재하는 것이 가능하므로, 자신만의 패키지 체계를 유지함으로써 다른 개발자가 개발한 클래스 라이브러리의 클래스와 이름이 충돌하는 것을 피할 수 있음
- 클래스가 물리적으로 하나의 클래스파일(.class)인 것과 같이 패키지는 물리적으로 하나의 디렉토리
- 패키지도 다른 패키지를 포함할 수 있으며 점'.'으로 구분
- 하나의 소스파일에는 첫 번째 문장으로 단 한 번의 패키지 선언만을 허용
- 모든 클래스는 반드시 하나의 패키지에 속해야 함
- 패키지는 점(.)을 구분자로 하여 계층구조로 구성할 수 있음
- 패키지는 물리적으로 클래스 파일(.class)을 포함하는 하나의 디렉토리
3.2 패키지의 선언
package 패키지명;
- 클래스나 인터페이스의 소스파일(.java)의 맨 위에 한 줄만 적어주면 됨
- 패키지 선언문은 반드시 소스파일에서 주석과 공백을 제회한 첫 번째 문장잉야 하며, 하나의 소스파일에 단 한 번만 선언될 수 있음
- 해당 소스파일에 포함된 모든 클래스나 인터페이스는 선언된 패키지에 속하게 됨
- 패키지명은 대소문자를 모두 허용하지만, 클래스명과 쉽게 구분하기 위해서 소문자로 하는 것을 원칙으로 함
- 소스파일에 자신이 속할 패키지를 지정하지 않은 클래스는 자동적으로 '이름 없는 패키지'에 속하게 됨. 패키지를 지정하지 않는 모든 클래스들은 같은 패키지에 속하게 됨
- 큰 프로젝트나 Java API와 같은 클래스 라이브러리를 작성하는 경우에는 미리 패키지를 구성하여 적용
3.3 import 문
- 클래스의 코드를 작성하기 전에 import문으로 사용하고자 하는 클래스의 패키지를 미리 명시해주면 소스코드에 사용되는 클래스이름에서 패키지명은 생략할 수 있음
- import문의 역할: 컴파일러에게 소스파일에 사용된 클래스의 패키지에 대한 정보를 제공하는 것
- 컴파일 시 컴파일러는 import문을 통해 소스파일에 사용된 클래스들의 패키지를 알아 낸 다음, 모든 클래스 이름 앞에 패키지명을 붙여줌
이클립스는 단축키 ctrl + shift + o
를 누르면, 자동으로 import문을 추가해줌
3.4 import문의 선언
소스파일(*.java)의 구성
1. package문
2. import문
3. 클래스 선언
import문 선언 방법
import 패키지명.클랫스명;
or
import 패키지명.*;
- 같은 패키지에서 여러 개의 클래스가 사용될 때, import문을 여러 번 사용하는 대신
패키지명.*
을 이요해서 지정된 패키지에 속한 모든 클래스를 패키지명 없이 사용할 수 있음
java.lang
패키지는 매우 빈번히 사용되는 중요한 클래스들이 속한 패키지이기 때문에 따로 import문을 지정하지 않아도 됨
3.5 static import문
- static import문을 사용하면 static멤버를 호출할 때 클래스 이름을 생략할 수 있음
- 특정 클래스의 static 멤버를 자주 사용할 때 편리
import static java.lang.Integer.*; // Integer 클래스의 모든 static 메서드
import static java.lang.Math.random; // Math.random()만. 괄호 안 붙임
import static java.lang.System.out; // System.out을 out만으로 참조 가능
System.out.println(Math.random()) -> out.println(random())
Author And Source
이 문제에 관하여([Chapter 7] 객제지향 프로그래밍 2_1), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@slchoi/Chapter-7-객제지향-프로그래밍-21
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
- 패키지에는 클래스 또는 인터페이스를 포함시킬 수 있음
- 서로 관련된 클래스들끼리 그룹 단위로 묶어 놓음으로써 클래스를 효율적으로 관리할 수 있음
- 하나의 소스파일에는 첫 번째 문장으로 단 한 번의 패키지 선언만을 허용
- 모든 클래스는 반드시 하나의 패키지에 속해야 함
- 패키지는 점(.)을 구분자로 하여 계층구조로 구성할 수 있음
- 패키지는 물리적으로 클래스 파일(.class)을 포함하는 하나의 디렉토리
package 패키지명;
- 해당 소스파일에 포함된 모든 클래스나 인터페이스는 선언된 패키지에 속하게 됨
- 컴파일 시 컴파일러는 import문을 통해 소스파일에 사용된 클래스들의 패키지를 알아 낸 다음, 모든 클래스 이름 앞에 패키지명을 붙여줌
이클립스는 단축키 ctrl + shift + o
를 누르면, 자동으로 import문을 추가해줌
소스파일(*.java)의 구성
1. package문
2. import문
3. 클래스 선언
import문 선언 방법
import 패키지명.클랫스명;
or
import 패키지명.*;
- 같은 패키지에서 여러 개의 클래스가 사용될 때, import문을 여러 번 사용하는 대신
패키지명.*
을 이요해서 지정된 패키지에 속한 모든 클래스를 패키지명 없이 사용할 수 있음 java.lang
패키지는 매우 빈번히 사용되는 중요한 클래스들이 속한 패키지이기 때문에 따로 import문을 지정하지 않아도 됨
import static java.lang.Integer.*; // Integer 클래스의 모든 static 메서드
import static java.lang.Math.random; // Math.random()만. 괄호 안 붙임
import static java.lang.System.out; // System.out을 out만으로 참조 가능
System.out.println(Math.random()) -> out.println(random())
Author And Source
이 문제에 관하여([Chapter 7] 객제지향 프로그래밍 2_1), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@slchoi/Chapter-7-객제지향-프로그래밍-21저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)