스프링 부트 강의를 들으면서 애매한 개념들을 확실히 정리하기 위해 씁니다.
: (is-a관계) 한 클래스가 다른 클래스의 변수와 메소드를 받아오는 것. 자식 클래스가 부모클래스를 상속받는다. 필요한 변수나 메서드를 추가할 수 있다.
class [자식 클래스] extends [부모 클래스] {}
// 부모 클래스
class Vehicle {
protected String brand; // 차량 브랜드
protected int year; // 제조 연도
public Vehicle(String brand, int year) {
this.brand = brand;
this.year = year;
}
public void start() {
System.out.println("Vehicle is starting");
}
public void stop() {
System.out.println("Vehicle is stopping");
}
}
// 자식 클래스 1: Car
class Car extends Vehicle {
private int doors; // 차량의 문 개수
public Car(String brand, int year, int doors) {
super(brand, year); // 부모 클래스의 생성자 호출
this.doors = doors;
}
// 추가 메소드 정의
public void openTrunk() {
System.out.println("Opening the trunk");
}
}
// 자식 클래스 2: Truck
class Truck extends Vehicle {
private double loadCapacity; // 적재 용량
public Truck(String brand, int year, double loadCapacity) {
super(brand, year); // 부모 클래스의 생성자 호출
this.loadCapacity = loadCapacity;
}
// 추가 메소드 정의
public void unload() {
System.out.println("Unloading cargo");
}
}
// 메인 클래스로 실행을 위한 코드
public class Main {
public static void main(String[] args) {
Car myCar = new Car("Toyota", 2021, 4);
Truck myTruck = new Truck("Ford", 2019, 5.0);
myCar.start();
myCar.openTrunk();
myCar.stop();
myTruck.start();
myTruck.unload();
myTruck.stop();
}
}
: 한 클래스는 단 하나의 부모클래스를 가져야한다.
하지만 여러 클래스의 메서드가 필요한 경우가 있다. 이때, 인터페이스를 이용하여 하나의 클래스가 여러 인터페이스를 구현함으로써 이 부분을 어느 정도 극복할 수 있다.
//인터페이스1 정의
public interface Sell {
void sell();
}
//인터페이스2 정의
public interface Buy {
void buy();
}
//인터페이스1,2를 모두 구현하는 클래스 정의
public class Customer implements Buy, Sell{
@Override
public void sell() {
System.out.println("customer sell");
}
@Override
public void buy() {
System.out.println("customer buy");
}
public void sayHello() {
System.out.println("Hello");
}
}
public class Main {
public static void main(String[] args) {
Customer customer1 = new Customer();
customer1.sell(); // 출력: customer sell
customer1.buy(); //출력: customer buy
}
}
: 메소드의 이름, 파라미터 리스트, 반환 유형을 명시하지만 코드적인 구현은 포함하지 않은 껍데기 클래스.
interface [인터페이스] {}
class [클래스] implements [인터페이스 이름] {}
class [클래스] implements [인터페이스1],[인터페이스2] {}
위와 같이 두 개의 인터페이스를 구현할 수 있다.
// Animal 인터페이스 정의
interface Animal {
void speak(); // 모든 동물은 말할 수 있어야 함을 정의
}
// Dog 클래스가 Animal 인터페이스를 구현
class Dog implements Animal {
// 인터페이스의 speak 메서드 구현
@Override
public void speak() {
System.out.println("멍멍!");
}
}
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.speak(); // 출력: 멍멍!
}
}
: 인터페이스와 유사한 역할.
인터페이스와의 차이점은 일부 메소드의 구현을 포함한다는 것이다. 또한 클래스 내에 변수(멤버 변수)를 가질 수 있다.
➜ 결과적으로 공통 부분을 추상 클래스에서 구현하여 코드의 중복을 줄인다.
abstract class [추상 클래스 이름] {}
class [클래스 이름] extends [추상 클래스 이름] {}
// Vehicle 추상 클래스 정의
abstract class Vehicle {
abstract void startEngine(); // 엔진을 시작하는 추상 메서드
// 공통 기능을 제공하는 비추상 메서드
void stopEngine() {
System.out.println("엔진 정지!");
}
}
// Car 클래스가 Vehicle 클래스를 상속받음
class Car extends Vehicle {
// 추상 메서드 구현
void startEngine() {
System.out.println("엔진 시동!");
}
}
public class Main {
public static void main(String[] args) {
Car myCar = new Car();
myCar.startEngine(); // 출력: 엔진 시동!
myCar.stopEngine(); // 출력: 엔진 정지!
}
}