TIL-23-03-07
Updated:
오버라이딩
- 조상 클래스로부터 상속받은 메서드의 내용을 변경하는 작업
- override의 사전적 정의는 ‘~위에 덮어쓰다(overwrite)’이다.
오버라이딩의 조건
- 선언부가 조상클래스의 메서드와 일치해야 한다.(메서드 이름, 매개변수, 반환타입)
- 접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경 할 수 없다.
- 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없다. (같거나 적어야 한다.)
class Point3 {
int x;
int y;
public String toString(){
return "x: " + x + ", y: " + y;
}
}
class Point3D extends Point {
int z;
public Point3D(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
public String toString(){ //오버라이딩
return "x: " + x + ", y: " + y + ", z: " + z;
}
}
public class OverrideTest {
public static void main(String[] args) {
Point3D p = new Point3D(2,3,1);
System.out.println(p);
}
}
오버로딩 vs 오버라이딩
오버로딩 기존에 없는 새로운 메서드를 정의하는 것(new) 오버라이딩 상속받은 메서드의 내용을 변경하는 것(change, modify)
class Parent {
void ParentMethod () {}
}
class Child extends Parent {
void ParentMethod() {} //오버라이딩
void ParentMethod(int i) {} //오버로딩
void childMethod() {}
void childMethod(int i) {} //오버로딩
void childMethod() {} //에러. 중복 정의되었음
}
super
- 객체 자신을 가리키는 참조변수이다.
- 조상의 멤버를 자신의 이름과 구별할 때 사용한다.
- 인스턴스메서드에서만 사용 가능하다.
import java.awt.*;
public class SuperTest {
public static void main(String[] args) {
Child c = new Child();
c.method();
}
}
class Parent {
int x= 10;
}
class Child extends Parent {
int x = 20;
void method() {
System.out.println("x=" + x);
System.out.println("this.x=" + this.x);
System.out.println("super.x=" + super.x);
}
}
- 메서드도 super로 호출이 가능하다.
- 특히 조상 클래스의 메서드를 자손 클래스에서 오버라이딩한 경우 super를 사용한다.
class Point {
int x;
int y;
public String toString(){
return "x: " + x + ", y: " + y;
}
}
class Point3D extends Point {
int z;
public String toString(){ // 오버라이딩
return "x: " + x + ", y: " + y + ", z: " + z;
return super.toString(); // 조상의 메서드 호출
}
}
super() - 조상 클래스의 생성자
- 조상 클래스의 생성자를 호출할 때 사용됨
- 생성자의 첫 줄에서 조상클래스를 호출하는 이유는, 자손 클래스의 멤버가 조상 클래스의 멤버를 사용할 수도 있으므로 조상의 멤버들이 먼저 초기화되어 있어야 하기 때문이다.
- 따라서, Object 클래스를 제외한 모든 클래스의 생성자 첫 줄에 반드시 생성자를 호출해야 한다. 그렇지 않으면 컴파일러가 자동적으로 ‘super();’를 생성자 첫 줄에 삽입한다.
import java.awt.*;
class Point3 {
int x;
int y;
Point3 (int x, int y) {
this.x = x;
this.y = y;
}
public String toString(){
return "x: " + x + ", y: " + y;
}
}
class Point3D extends Point {
int z;
public Point3D(int x, int y, int z) {
// 생성자 첫 줄에서 다른 생성자를 호출하지 않았으므로 컴파일러가 'super();'를 여기에 삽입힌다.
// super()는 Point3D의 조상인 Point클래스의 기본 생성자 Point()를 의미한다.
this.x = x;
this.y = y;
this.z = z;
}
public String toString(){ // 오버라이딩
return "x: " + x + ", y: " + y + ", z: " + z;
}
}
public class PointTest {
public static void main(String[] args) {
Point3D p = new Point3D(2,3,1);
}
}
- 해결방법은 1) Point 클래스에 생성자 Point()를 추가 2) 생성자 Point3D 첫줄에 Point(int x, int y)를 호출하도록 변경한다.
- 조상 클래스의 멤버변수는 조상 생성자에 의해 초기화되도록 해야한다.
public Point3D(int x, int y, int z) { super(x, y) this.z = z; }
패키지
- 서로 관련된 클래스의 묶음
- 클래스가 물리적으로 하나의 클래스파일(.class)인 것과 같이 패키지는 물리적으로 하나의 디렉토리이다.
- 클래스의 실제 이름은 패키지를 포함(java.lang.String)
- rt.jar는 클래스들을 압축한 파일(JDK 설치경로 \jre\lib)
패키지의 선언
- 패키지는 소스파일의 첫 번째 문장으로 단 한번 선언
- 같은 소스 파일의 클래스들은 모두 같은 패키지에 속하게 된다.
- 패키지 선언이 없으면 이름없는 패키지에 속하게 된다.
클래스 패스(classpath)
- 클래스 파일(*.class)의 위치를 알려주는 경로(path)
- 환경변수 classpath로 관리하며 경로간의 구분자는 ‘;’를 사용
- classpath(환경변수)에 패키지 루트를 등록해줘야 함
import문
- 클래스를 사용할 때 패키지이름을 생략할 수 있다.
- 컴파일러에게 클래스가 속한 패키지를 알려준다.
- java.lang 패키지의 클래스는 import하지 않고도 사용 가능함.(String, Object, System, Thread…)
- import문은 컴파일 시 처리되므로 프로그램 성능에 영향이 없음.
static import문
- static멤버를 사용할 때 클래스 이름을 생략할 수 있다.
- 특정 클래스의 static 멤버를 자주 사용할 때 편리하다.
import static java.lang.System.out;
out.println(random());