Java
[Java] 상속
Dev_Fuji
2024. 6. 10. 22:26
상속
- 상속이란 부모가 자식에게 필드와 메서드를 물려주는 것을 의미
- 모든 클래스는 Object의 상속을 받는다(생략가능)
=> class A extends Object - 코드의 중복을 줄인다.
- 다중 상속을 허용하지 않는다.
public class SmartCalc extends Calc{
}
public class Calc {
public int number;
}
public static void main(String[] args) {
SmartCalc sc = new SmartCalc();
sc.number=10;
System.out.println("sc.number => " + sc.number );
}
> Task :Main.main()
Calc create
SmartCalc create
sc.number => 10
- 자식클래스 생성 시 부모 클래스가 먼저 생성되고 자식이 생성 된다.
=> 자식 생성자 첫 줄 super()에 의해 생성, super()은 컴파일 과정에서 자동 추가, 이것이 부모 기본 생성자 호출, 만일 부모 기본 생성자가 없으면 에라 발생=> super(매개변수,) 로 생성자 호출 가능
=> 싱글턴 객체는 상속이 불가 => 생성자가 private여서 자식에서 접근 불가 - 자식은 부모의 메소드를 오버라이딩을 통해 재정의할 수 있다.
1. 리턴타입, 메소드이름, 매개변수가 동일해야 한다.
2. 접근제한자를 더 강하게 할 수 없다.(public => private 불가)
3. 새로운 예외처리 불가
public class Calc {
public int number;
public double getCircle(){
return number*3.14*number;
}
}
public class SmartCalc extends Calc{
public SmartCalc() {
System.out.println("SmartCalc create");
}
@Override
public double getCircle(){
return number*3*number;
}
}
public class SmartCalc2 extends Calc{
@Override
public double getCircle(){
return super.getCircle();
}
}
public static void main(String[] args) {
SmartCalc sc = new SmartCalc();
Calc c = new Calc();
sc.number=10;
c.number=10;
System.out.println("sc.getCircle => " + sc.getCircle() );
System.out.println("c.getCircle => " + c.getCircle() );
}
> Task :Main.main()
sc.getCircle => 300.0
c.getCircle => 314.0
- super.methods()를 사용하면 부모의 메소드를 자식에서 불러사용할 수 있다.
- 클래스 선언시 final을 붙이면 최종적인 클래스 이므로 더이상 상속할 수 없다.
=>final 클래스는 부모가될 수 없다.
- 메소드 선언시 final을 붙이면 자식에서 오버라이딩()할 수 없다.
타입변환
- 자동 타입 변환
부모class 변수 = 자식class();
=>자식은 부모의 필드와 메소드를 상속받기 때문에 동일 취급
=> 부모 클래스의 필드와 메서드만 접근이 가능. 오버라이딩된 메소드는 오버라이딩된 메소드가 호출된다.
public class Calc {
public int number;
public Calc() {
}
public double getCircle(){
return number*3.14*number;
}
}
public class SmartCalc extends Calc{
@Override
public double getCircle(){
return number*number*3;
}
}
public class Main {
public static void main(String[] args) {
SmartCalc sc = new SmartCalc();
Calc c = new Calc();
Calc cChild = sc;
sc.number=10;
c.number=10;
System.out.println("sc==cChild =>"+(sc==cChild));
System.out.println("sc.getCircle() =>"+sc.getCircle());
System.out.println("c.getCircle() =>"+c.getCircle());
System.out.println("cChild.getCircle() =>"+cChild.getCircle());
}
}
> Task :Main.main()
sc==cChild =>true //동일한 주소를 가진다
sc.getCircle() =>300.0
c.getCircle() =>314.0
cChild.getCircle() =>300.0 //오버라이딩된 메소드를 사용
- 강제 타입 변환
자식class 변수 = (자식class) 부모class
자식=> 부몬는 자동 변환 되지만, 부모=>자식 자동변환 되지 않는다
자식 타입의 변수와 메소드에 접근이 가능하다
다형성
- 메소드는 같지만 결과가 다른 성질(오버라이딩 이용)
- 자동타입변환과 메소드 재정의가 필요
- 자식 클래스는 부모 클래스로 자동 타입 변환이 될 수 있고, 메소드를 재정의할 수 있다.
public class Main {
public static void main(String[] args) {
Computer computer = new Computer();
computer.calc= new SmartCalc(); // 자동 타입변환
Computer computer2 = new Computer();
computer2.calc= new DoubleCalc(); // 자동 타입변환
computer.calc.number=10;
computer2.calc.number=10;
System.out.println(computer.getCalc());
System.out.println(computer2.getCalc());
}
}
public class Computer {
public Calc calc; //자동 타입 변환
public double getCalc(){
return calc.getCircle(); //메소드 재저으이
}
}
public class Calc {
public int number;
public Calc() {
}
public double getCircle(){
return number*3.14*number;
}
}
public class DoubleCalc extends Calc {
@Override
public double getCircle(){
return 3.141592*number*number;
}
}
public class SmartCalc extends Calc{
@Override
public double getCircle(){
return number*number*3;
}
}
- 매개변수로도 가능하다
public class Main {
public static void main(String[] args) {
Calc sc = new SmartCalc();
Calc dc = new DoubleCalc();
sc.number=10;
dc.number=10;
Computer computer2 = new Computer(dc);
Computer computer = new Computer(sc);
}
}
public class Computer {
public Calc calc;
public Computer() {
}
public Computer(Calc calc) {
System.out.println(calc.getCircle());
}
public double getCalc(){
return calc.getCircle();
}
}
추상 클래스
- 클래스 선언부에 abstract를 붙이면 추상클래스로 선언된다.
- 객체를 생성할 수 있느 클래스의 공통적인 필드나 메소드를 추출해서 선언한 클래스가 추상클래스
- 실제 클래스의 부모의 역할을 한다.
- 필드, 메소드 선언이 가능하고 자식이 생성될 때 super를 부르므로 생성자가 반드시 있어야한다.
- 추상이기 때문에 new를 통한 직접생성은 불가능하다. => 상속을 통해 자식 클래스만 생성 가능
- 추상클래스는 extends뒤에만 나올 수 있다.
- 메소드 앞에 abstract를 붙여 추상 메소드를 선언할 수 있고 자식에서 반드시 재정의해야한다.
=> 반드시 추상메소드를 가질 필요는 없다.
=> 자식에서 재정의하지 않으려면 자식도 추상클래스여야한다.
=> 재정의되므로 추상 클래스는 메소드 내용 {}가 없다.
public abstract double getCircle();
봉인된 클래스
- Java 15부터 무분별한 자식 클래스 생성 방지를 위한 봉인된(sealed) 클래스 도입
- sealed를 통해 봉인을 선언하고 permits에 선언된 자식들만 상속 가능
- 상속 가능한 자식드은 final을 통해 더이상 상속이 불가능하게 선언하거나 non-sealed를 통해 봉인을 해제하여 자식은 자식을 만들 수 있도록 설정한다.
public sealed class Calc permits SmartCalc,DoubleCalc {
public int number;
public Calc() {
}
public double getCircle(){
return 3.14;
};
}
public final class DoubleCalc extends Calc { //extends 선언법 1
}
public non-sealed class SmartCalc extends Calc{ //extends 선언법 2, SmartCalc는 sealed가 해재되어 상속 가능
@Override
public double getCircle(){
return number*number*3;
}
public double getPi(){
return 3.14;
}
}