1. 상속
1.1 상속의 개념
- 부모클래스를 상속받은 자식클래스에서 부모클래스의 필드,메소드를 활용 하는 방법을 말한다.
- 부모클래스의 멤버를 자식클래스에 복사하는것이 아니라, 부모클래스의 멤버를 사용하는 것일 뿐이다.
- 직접적으로 바이트 코드를 복사하지 않는다.
1.2 클래스 상속
- 클래스 상속 extends를 사용하여 자식클래스가 부모클래스로 부터 상속 받았다는것을 표기한다.
public class Parent{
필드
메소드()
}
public class Child extends Parent{
필드
메소드()
}
1.3 부모 생성자 호출
- 클래스 상속을 받은 자식클래스를 인스턴스 하면 부모클래스의 생성자가 자동적(super())으로 호출된다.
public class SmartPhone extends Phone {
//자식 생성자 선언
public SmartPhone(String model, String color) {
super();
this.model = model;
this.color = color;
System.out.println("SmartPhone(String model, String color) 생성자 실행됨");
}
}
- 부모클래스의 생성자가 매개변수를 가지고 있다면, 자식클래스도 super(매개변수)의 구조로 사용해야한다.
1.4 메서드 오버라이딩
- 자식클래스에서 부모클래스의 메서드를 재정의 하는 방법이다.
- 부모 메서드의 선언부(리턴 타입, 메서드명, 매개변수)는 동일해야한다.
- 접근제한을 더 강하게 오버라이딩 할수 없다.
- 오버라이딩시 어노테이션(@override)를 사용하면 컴파일 오류를 막을 수 있다.
public class Computer extends Calculator {
//메소드 오버라이딩
@Override
public double areaCircle(double r) {
System.out.println("Computer 객체의 arearCircle() 실행");
return Math.PI * r * r;
}
}
1.5 부모메서드 호출
- 자식클래스에서 부모클래스의 메서드를 호출 시에는 super.부모메서드명()을 사용한다.
public class SupersonicAirplane extends Airplane {
//상수 선언
public static final int NORMAL = 1;
public static final int SUPERSONIC = 2;
//상태 필드 선언
public int flyMode = NORMAL;
//메소드 재정의
@Override
public void fly() {
if(flyMode == SUPERSONIC) {
System.out.println("초음속비행합니다.");
} else {
//Airpanle 객체의 fly() 메소드 호출
super.fly();
}
}
}
1.6 타입변환
- 자동 타입변환 : 부모클래스 타입의 변수가 자식 타입의 객체를 사용하면 자동 타입변환이 이 일어난다.
- 부모클래스에 선언된 필드와 메서드만 접근이 가능하다.
- 자식클래스에 오버라이딩 된 메서드가 있다면 오버라이딩 메소드가 실행된다.
package ch07.sec07.exam02;
public class ChildExample {
public static class Parent {
// 메소드 선언
public void method1() {
System.out.println("Parent-method1()");
}
// 메소드 선언
public void method2() {
System.out.println("Parent-method2()");
}
}
public static class Child extends Parent {
// 메소드 오버라이딩
@Override
public void method2() {
System.out.println("Child-method2()");
}
// 메소드 선언
public void method3() {
System.out.println("Child-method3()");
}
}
public static void main(String[] args) {
// 자식 객체 생성
// Child child = new Child();
// 자동 타입 변환
Parent parent = new Child();
// 메소드 호출
parent.method1(); //Parent-method1()
parent.method2(); // child-method2()
// parent.method3(); (호출 불가능)
}
}
- 강제 타입변환 : 자식클래스 타입의 변수가 부모클래스의 타입의 변수로 생성되면 강제(캐스팅)을 해야한다.
package ch07.sec07.exam03;
public class ChildExample {
public static class Parent {
// 필드 선언
public String field1;
// 메소드 선언
public void method1() {
System.out.println("Parent-method1()");
}
// 메소드 선언
public void method2() {
System.out.println("Parent-method2()");
}
}
public static class Child extends Parent {
// 필드 선언
public String field2;
// 메소드 선언
public void method3() {
System.out.println("Child-method3()");
}
}
public static void main(String[] args) {
// 객체 생성 및 자동 타입 변환
Parent parent = new Child();
// Parent 타입으로 필드와 메소드 사용
parent.field1 = "data1";
parent.method1();
parent.method2();
/*
* parent.field2 = "data2"; //(불가능) parent.method3(); //(불가능)
*/
// 강제 타입 변환
Child child = (Child) parent;
// Child 타입으로 필드와 메소드 사용
child.field2 = "data2"; // (가능)
child.method3(); // (가능)
}
}
1.7 다형성
- 자동 타입변환과 메서드 오버라이딩으로 인해 다형성이 가능해진다.
- 다형성이란 같은 메서드선어부로 다른 결과를 만들수 있는 성질을 말한다.
- 타이어 굴린다()의 메서드를 상속 받은 한국타이어,금호타이어가 있다고 가정하자.
- 타이어 : 굴린다() = 타이어가 굴러간다.
- 한국타이어 : 굴린다() = 한국 타이어가 굴러간다.
- 금호타이어 : 굴린다() = 금호 타이어가 굴러간다.
- 타이어 t1 = new 타이어 -> t1.굴린다() = 타이어가 굴러간다.
- 타이어 t1 = new 한국타이어 -> t1.굴린다() = 한국타이어가 굴러간다.
- 타이어 t1 = new 금호타이어 -> t1.굴린다() = 금호타이어가 굴러간다.
- 이러한 성질을 사용하면, 매개변수의 다형성을 만들 수 있다.
public class Driver {
//메소드 선언(클래스 타입의 매개변수를 가지고 있음)
public void drive(Vehicle vehicle) {
vehicle.run();
}
}
public class Vehicle {
//메소드 선언
public void run() {
System.out.println("차량이 달립니다.");
}
}
public class Bus extends Vehicle {
//메소드 재정의(오버라이딩)
@Override
public void run() {
System.out.println("버스가 달립니다.");
}
}
- 자동 타입 변환 : Vehicle vehicle = new Bus();
- 메서드 오버라이딩 : vehicle.run() - > bus.run()
public class DriverExample {
public static void main(String[] args) {
//Driver 객체 생성
Driver driver = new Driver();
//매개값으로 Bus 객체를 제공하고 driver 메소드 호출
Bus bus = new Bus();
driver.drive(bus);
//driver.drive(new Bus()); 와 동일
}
}
- 이것을 응용하면 instanceof와 강제 형변환을 통해 부모클래스의 변수를 자식 클래스의 멤버를 사용할 수 있게 한다.
public static void main(String[] args) {
// 수퍼 클래스의 레퍼런스는 하위 클래스의 인스턴스를 담을 수 있다.
Vehicle[] arr = new Vehicle[] {new Truck("기아자동차", 5, 10000, 32, 15f, true)};
printCar(arr[0]);
}
// Vehicle v = new Truck("기아자동차", 5, 10000, 32, 15f, true);
// 부모타입의 변수(v)로 자식타입(Truck)을 선언
static void printCar(Vehicle v) {
System.out.printf("모델: %s\n", v.model);
System.out.printf("수용인원: %s\n", v.capacity);
// v는 car의 부모클래스
// car 가능
if (v instanceof Car) {
Car c = (Car) v;
System.out.printf("cc: %s\n", c.cc);
System.out.printf("밸브: %s\n", c.valve);
if (v instanceof Sedan) {
Sedan s = (Sedan) v;
System.out.printf("썬루프: %b\n", s.sunroof);
System.out.printf("오토: %b\n", s.auto);
} else if (v instanceof Truck) {
//강제 형변환
Truck t = (Truck) v;
//오버라이딩 메서드 실행
System.out.printf("톤: %f\n", t.ton);
System.out.printf("덤프여부: %b\n", t.dump);
}
} else if (v instanceof Bike) {
Bike b = (Bike) v;
System.out.printf("engine: %b\n", b.engine);
}
System.out.println("-----------------------");
}
}
1.8 추상클래스
- 추상메서드는 클래스들간에 공통적인 멤버를 선언하되 부모클래스를 직접적으로 사용할 수 없는 클래스이다.
- 추상클래스 이기 때문에 new연산자를 통해 직접적인 생성을 불가능하다.
- 자식클래스에서 상속을 받아 사용 해야한다.
- 상속 받은 클래스에서는 필드, 메서드 생성자를 사용할 수 있다.
// 추상 클래스 선언
public abstract class Phone {
//필드 선언
String owner;
//생성자 선언
Phone(String owner) {
this.owner = owner;
}
//메소드 선언
void turnOn() {
System.out.println("폰 전원을 켭니다.");
}
//메서드 선언만 있으면 상속받은 클래스에서는 메서드를 완성해야한다.
void internetSearch();
void turnOff() {
System.out.println("폰 전원을 끕니다.");
}
}
// 자식 클래스
public class SmartPhone extends Phone {
//생성자 선언
SmartPhone(String owner) {
//Phone 생성자 호출
super(owner); //부모클래스의 생성자가 있으므로 생성해야한다.
}
//메소드 선언
//메서드 선언만 있으면 상속받은 클래스에서는 메서드를 완성해야한다.
void internetSearch() {
System.out.println("인터넷 검색을 합니다.");
// 자식 클래스에서 추상클래스의 메서드를 오버라이딩 할 수 있다.
@override
void turnOff() {
System.out.println("스마트폰 전원을 끕니다.");
}
}
public class PhoneExample {
public static void main(String[] args) {
//Phone phone = new Phone();
SmartPhone smartPhone = new SmartPhone("홍길동");
smartPhone.turnOn(); //전원을 킵니다.
smartPhone.internetSearch(); //인터넷 검색을 합니다.
smartPhone.turnOff(); //스마트폰 전원을 끕니다.
}
}
1.9 this와 super
this | super | |
메서드 | 현재 객체가 선언된 클래스의 메서드 | 현재 객체의 부모클래스 |
필드 | 현재 객체의 필드 | 현재 객체의 부모 메서드 |
package study.oop.clazz;
public class TestThis {
static class A {
String name = "A";
boolean working = true;
void print() {
System.out.println("A.print():");
System.out.printf(" => this.name(%s)\n", this.name);
System.out.printf(" => this.working(%s)\n", this.working);
}
void m1() {
System.out.println("super.m1() 메서드=> A.m1()");
}
}
static class A2 extends A {
String name = "A2";
int age = 20;
@Override
void print() {
System.out.println("A2의 print문");
System.out.printf("this.name 필드 = > %s\n", this.name);
this.m1();
System.out.printf("super.name 필드 = > %s\n", super.name);
super.m1();
}
@Override
void m1() {
System.out.println("A2.m1()");
}
}
static class A3 extends A2 {
String name = "A3";
String gender = "남";
@Override
void m1() {
System.out.println("this.m1() 메서드=> A3.m1()");
}
}
public static void main(String[] args) {
A2 obj = new A3();
obj.print();
}
}
- 결과
A2의 print문
this.name 필드 = > A2
this.m1() 메서드=> A3.m1()
super.name 필드 = > A
super.m1() 메서드=> A.m1()
- 메서드의 경우 override가 필요하여 A3로 선언된 오버라이딩이 우선
- 필드의 경우 override가 없으니 A2가 우선
'개발자 꿈나무의 하루 > 01_Boot Camp' 카테고리의 다른 글
(네이버클라우드 부트캠프) 29일차 - Java프로그래밍 기초(인터페이스) (1) | 2024.07.05 |
---|---|
(네이버클라우드 부트캠프) 28일차 - Java프로그래밍 기초(추상클래스, 인터페이스,캡슐화) (0) | 2024.07.03 |
(네이버클라우드 부트캠프) 24_25일차 - 미니프로젝트 가계부만들기 (0) | 2024.07.01 |
(네이버클라우드 부트캠프) 23일차 - 실습프로젝트(인터페이스) (0) | 2024.06.26 |
(네이버클라우드 부트캠프) 22일차 - Java프로그래밍 기초(String, Wrapper),실습프로젝트(LinkedList) (0) | 2024.06.25 |