01. 상속
- 상속이란, 기존의 클래스를 재 사용하여 새로운 클래스를 작성하는 것이다.
- 상속을 통해서 클래스를 작성하면 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있고, 코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 변경이 매우 용이하다.
- 생성자와 초기화 블럭은 상속되지 않는다. 멤버만 상속된다.
- 자손 클래스의 멤버 개수는 조상 클래스보다 항상 같거나 많다.
- 다중 상속을 허용하지 않는다.
- 조상 클래스만 변경해도 모든 자손 클래스에, 자손의 자손 클래스에까지 영향을 미치기 때문에, 클래스간의 상속 관계를 맺어주면 자손 클래스들의 공통적인 부분은 조상 클래스에서 관리하고 자손 클래스는 자신에 정의된 멤버들만 관리하면 되므로 각 클래스의 코드가 적어져서 관리가 쉬워진다.
- 상속관계 : "~은 ~이다.(is-a)"
- 포함 관계: "~은 ~을 가지고 있다.(has-a)"
EX)
A Circle is a Shape // 1. 원은 도형이다
A Cricle is a Point // 2. 원은 점이다?
A Circle has a Shape // 3. 원은 도형을 가지고 있다?
A Circle has a Point // 4. 원은 점을 가지고 있다.
상속 관계시 is-a가 가장 자연스럽다.
02. 오버라이딩
- 조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것
- 자손 클래스 자신에 맞게 변경하는 것
- 오버라이딩의 조건:
1. 이름이 같아야 한다.
2. 매개변수가 같아야 한다.
3. 반환타입이 같아야 한다.
-오버라이딩시, 접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다. (public > protected > (default) > private)
- 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없다.
- 오버로딩은 기존에 없는 새로운 메서드를 정의하는 것(new라는 표현에 가깝다)
반면 오버라이딩은 상속받은 메서드의 내용을 변경하는 것(change,modify)
- super()는 조상 클래스의 생성자를 호출하는데 사용된다. 최상위 Object클래스를 제외한 모든 클래스의 생성자는 첫 줄에 반드시 자신의 다른 생성자 또는 조상의 생성자를 호출해야 한다. 그렇지 않으면 컴파일러는 생성자의 첫 줄에 super();를 자동적으로 추가할 것 이다.
class PointTest {
public static void main(String[] args) {
Point3D p3 = new Point3D(1,2,3);
}
}
class Point{
int x, y;
Point(int x,int y){
// 생성자 첫줄에서 다른 생성자를 호출하지 않기 때문에 컴파일러가 'super();'를 여기에 삽입한다
// super()는 Point의 조상인 Object클래스의 기본 생성자인 Object()를 의미한다.
this.x = x;
this.y = y;
}
String getLocation(){
return "x: " + x + ", y: " + y;
}
}
class Point3D extends Point {
int z;
Point3D(int x, int y, int z){ // 컴파일 에러, super();를 insert해야함
this.x = x;
this.y = y;
this.z = z;
}
String getLocation(){
return "x : " + x + ",y :" + y + ", z:" + z;
}
}
class PointTest {
public static void main(String[] args) {
Point3D p3 = new Point3D(1,2,3);
}
}
class Point{
int x, y;
Point(int x,int y){
this.x = x;
this.y = y;
}
String getLocation(){
return "x: " + x + ", y: " + y;
}
}
class Point3D extends Point {
int z;
Point3D(int x, int y, int z){ // 컴파일 에러, super();를 insert해야함
//super(); // 컴파일 에러 -> Point클래스에 Point()가 정의되어 있지 않음
this.x = x;
this.y = y;
this.z = z;
}
String getLocation(){
return "x : " + x + ",y :" + y + ", z:" + z;
}
}
위의 경우에는 super(x,y)나, Point클래스에 Point() 생성자를 추가해주면 된다. 조상 클래스의 멤버 변수는 조상의 생성자에 의해 초기화되도록 해야 한다.
여기서
Point3D p3 = new Point3D(); 로 인스턴스를 생성하면,
이 순으로 생성자가 호출됩니다.
Point3D() -> Point3D(int x, int y, int z) -> Point(int x, int y) -> Object()
3. package와 import
- 패키지란 클래스의 묶음이다.
- 모든 클래스는 반드시 하나의 패키지에 포함되어야 한다.
- 패키지를 선언하지 않으면 자동적으로 '이름 없는 패키지'에 속하게 된다.
- static import문을 사용하면 static 멤버를 호출할 때 클래스 이름을 생략할 수 있다.
import static java.lang.System.out;
import static java.lang.Math.*;
public class StaticImportEx1 {
public static void main(String[] args) {
//System.out.println(Math.random());
out.println(random());
//System.out.println("Math.PI:" + Math.PI);
out.println("Math.PI" + PI);
}
}
4. 제어자
- 제어자는 클래스, 변수 또는 메서드의 선언부에 함께 사용되며 부가적인 의미를 부여합니다 .
- 제어자의 종류는 크게 접근 제어자와 그 외 제어자로 나눌 수 있습니다.
- 접근 제어자: public, protected, default, private
그 외 : static, final, abstract, native, transient, synchronized, volatiel ,strictfp
- static은 '클래스의' 또는 '공통적인'의 의미를 지니고 있으며 static이 붙은 멤버변수와 메서드, 그리고 초기화 블럭은 클래스에 관계된 것이기 때문에 인스턴스를 생성하지 않고도 사용할 수 있다.
- final은 '마지막'의 또는 '변경될 수 없는'의 의미를 가지고 있으며 거의 모든 대상에 사용될 수 있다. 변수에 사용되면 상수가 되며 메서드에 사용되면 오버라이딩 불가능하고, 자신을 확장하는 자손 클래스를 정의하지 못하게 된다.
제어자 | 대상 | 의미 |
final | 클래스 | 변경될 수 없는 클래스로 final로 지정된 클래스는 상속할 수 없다. |
메서드 | 변경될 수 없는 메서드로 재정의될 수 없다. | |
멤버변수 | 값을 변경할 수 없는 상수가 된다. | |
지역변수 |
- abstract : 메서드의 선언부만 작성하고 실제 수행내용은 구현하지 않은 추상 메서드를 사용하는데 사용된다.
클래스와 메소드에 사용할 수 있으며, 클래스에 사용할 경우 추상 메서드가 선언되어 있음을 의미하며, 메서드 앞에 사용될 경우 선언부만 작성하고 구현부는 작성하지 않은 추상 메서드임을 알림
- 접근 제어자는 멤버 또는 클래스에 사용되어, 해당하는 멤버 또는 클래스를 외부에서 접근하지 못하도록 제한하는 역할을 한다.
- private : 같은 클래스 내에서만 접근 가능
- default : 같은 패키지 내에서만 접근 가능
- protected : 같은 패키지 내에서, 그리고 다른 패키지의 자손 클래스에서 접근이 가능하다.
- public : 접근 제한이 전혀 없다.
접근 제어자를 사용하는 이유는 클래스 내부에 선언된 데이터를 보호하기 위해서이다. 이는 객체지향의 캡슐화와도 연관이 있다.
- 생성자가 private인 클래스는 다른 클래스의 조상이 될 수 없으므로, 앞에 final을 추가하여 상속할 수 없는 클래스라는 것을 알리는게 좋다.
* 주의사항
- 1. 메서드에 static과 abstract를 함께 사용할 수 없다. (static은 몸통이 있는 메서드에만 사용 가능하다)
2. 클래스에 abstract와 final을 동시에 사용할 수 없다. ( final은 클래스를 확장할 수 없다는 뜻이고, abstract는 상속을 통해서 완성되므로)
3. abstract메서드의 접근 제어자가 private일 수 없다. (abstract메서드는 자손 클래스에서 구현해주어야 하는데 접근제어자가 private이면 자손 클래스에서 접근할 수 없기 때문이다)
4. 메서드에 private과 final을 같이 사용할 필요는 없다. ( 어차피 둘 다 오버라이딩 못하므로 하나만 사용해도 충분함)
5. 다형성
- 다형성이란, 여러가지 형태를 가질 수 있는 능력으로, 구체적으로 예를 들자면 조상 클래스 타입의 참조변수로 자손 클래스의 인스턴스를 참조할 수 있도록 하는 것.
- 자손 타입의 참조변수로 조상타입의 인스턴스를 참조하는 것은 가능하지 않다 -> 존재하지 않는 멤버를 사용하고자 할 가능성이 있으므로
6. 추상 클래스
- 미완성 설계도에 비유할 수 있음.
- abstract 키워드를 붙이면 됨
- 생성자, 멤버변수, 메서드 가질 수 있음
- 인스턴스 생성 불가
- abstract 리턴타입 메서드이름();
'Language > Java' 카테고리의 다른 글
java.lang패키지와 유용한 클래스 (0) | 2021.12.19 |
---|---|
예외처리 (2) | 2021.12.12 |
완독 스터디 - 객체지향 프로그래밍1 (0) | 2021.11.28 |
직렬화와 역직렬화 (0) | 2021.11.17 |
Java Checked Excpetion, UnChecked Exception (0) | 2021.09.26 |