[Java] 클래스 간의 관계

김용준·2022년 10월 5일
0

Java Basic

목록 보기
20/22

클래스 간의 관계

객체지향프로그래밍에서는 클래스를 통해 객체를 생성하고, 그 객체들이 상호작용하며 프로그램의 기능을 수행한다.

인간, 침팬지, 고릴라가 영장류에 속해 있는 것처럼 현실세계에 존재하는 개념들은 상위, 하위 개념으로 나뉜다. 또는 자동차를 구성하는 부품 중 엔진이 있는 것 처럼 한 개념이 다른 개념의 부분일 수도 있다. 이처럼 프로그램의 클래스도 다양한 관계를 맺고 있다.

포함 관계 (has a 관계)

클래스의 멤버 변수로 또 다른 클래스를 정의한 관계다. 즉, 객체의 속성으로 다른 객체를 갖는다.

다음은 Car클래스의 멤버변수로 Engine클래스를 정의한 예제이다.

public class Car {

	String maker;
	String type; 
	
	// Engine객체를 멤버변수로 갖는다.
	Engine engine;
	
}
public class Engine {

	String fuelType;
	int maxRpm;
	double maxTorque;
	
}

Engine객체를 생성한 후, Car객체의 멤버변수에 대입했다.

public class CarApp {
	
	public static void main(String[] args) {

		Engine engine = new Engine();
		engine.fuelType = "gasoline";
		engine.maxRpm = 6000;
		engine.maxTorque = 54.8;
		
		Car car = new Car();
		car.engine = engine;
		car.maker = "BMW";
		car.type = "sedan";
		
	}
}

위와 같이 Car객체의 멤버변수에 직접 대입하는 방법 외에도 생성자나 set()메소드를 통해 간접적으로 대입하는 방법이 있다. 이를 의존성주입(Dependency Injection) 이라고 한다. 객체지향 5원칙 중 하나인데, 이는 추후에 보다 자세히 다루도록 하겠다. 아래 예제를 통해 이해해보자.

public class Car {

	String maker;
	String type; 
	
	// Engine객체를 멤버변수로 갖는다.
	Engine engine;

	public Car() {}
	
	// engine객체를 매개변수로 전달받는 생성자
	public Car(Engine engine) {
		this.engine = engine;
	}

	// engine객체를 매개변수로 전달받는 메소드
	public void setEngine(Engine engine) {
		this.engine = engine;
	}
	
}
public class CarApp {
	
	public static void main(String[] args) {

		Engine engine1 = new Engine();
		engine1.fuelType = "gasoline";
		engine1.maxRpm = 6000;
		engine1.maxTorque = 54.8;
		
		// 생성자를 통한 engine1객체 대입
		Car car1 = new Car(engine1);
		car1.maker = "BMW";
		car1.type = "sedan";
		
		Engine engine2 = new Engine();
		engine2.fuelType = "diesel";
		engine2.maxRpm = 5000;
		engine2.maxTorque = 60.2;
		
		// setter메소드를 통한 engine2객체 대입
		Car car2 = new Car();
		car2.setEngine(engine2);
		car2.maker = "Benz";
		car2.type = "SUV";
		
	}
}

상속 관계 (is a 관계)

클래스를 상위 클래스와 하위 클래스로 나누어 상위 클래스의 필드와 메소드를 하위 클래스가 말 그대로 '상속'받는 관계이다. 하위 클래스는 상속받은 필드와 메소드를 상위 클래스와 같이 완전히 동일하게 이용할 수 있다. 이때 하위 클래스만의 고유한 필드와 메소드롤 추가로 정의할 수 있다. extends키워드를 사용해 상속 관계를 정의한다. 상속에 대해서는 다음 포스팅에서 보다 자세히 다루도록 한다.

다음은 Phone클래스를 정의하고 그 속성과 기능을 SmartPhone클래스가 상속받은 예제이다.

public class Phone {

	String number;
	
	public void tel() {
		System.out.println("[" + this.number + "]의 전화 기능 실행");
	}
	
	public void sms() {
		System.out.println("[" + this.number + "]의 문자 기능 실행");
	}
}
// Phone클래스로부터 상속받은 클래스다.
public class SmartPhone extends Phone {
	
	// 상속받은 필드 외에 별로도 정의한 필드다.
	String email;
	String ip;
	
	// 상속받은 필드 외에 별로도 정의한 메소드다.
	public void sendEmail() {
		System.out.println("["+email+"] 이메일을 보내기 기능을 실행합니다.");
	}
	
	public void internet() {
		System.out.println("["+ip+"] 인터넷 기능을 실행합니다.");
	}

}
public class PhoneApp {

	public static void main(String[] args) {
		
        // 멤버변수 number는 SmartPhone에서 정의하지 않았지만 
        // Phone으로부터 상속받았기 때문에 사용 가능하다.
		SmartPhone smartPhone = new SmartPhone();
		smartPhone.number = "010-2222-4444";
		smartPhone.email = "aa@gmail.com";
		smartPhone.ip = "125.177.000.00";
		
        // tel()과 sms()메소드는 SmartPhone에서 정의하지 않았지만 
        // Phone으로부터 상속받았기 때문에 사용 가능하다.
		smartPhone.tel();
		smartPhone.sms();
		smartPhone.sendEmail();
		smartPhone.internet();
		
	}
}
출력

[010-2222-4444]의 전화 기능 실행
[010-2222-4444]의 문자 기능 실행
[aa@gmail.com] 이메일을 보내기 기능을 실행합니다.
[125.177.000.00] 인터넷 기능을 실행합니다.
profile
차선이 모여 최선이 된다.

0개의 댓글