본문 바로가기
java/java 리팩토링

08. 상속을 위임으로 바꾸기

by 문자메일 2023. 2. 12.

IS-A 관계와 HAS-A 관계

  • IS-A 관계
    • 일반적인 클래스와 구체적인 클래스의 관계
    • 클래스간의 상속은 종속성이 강하므로 꼭 필요한 경우 사용하는 것이 좋다.
    • 상속은 코드 재사용을 위한 방법이 아니다.
  • HAS-A 관계
    • 이미 잘 만들어진 라이브러리나 클래스를 재사용하는 방법
    • 사용할 클래스를 포함하여 그 기능을 해당 클래스로 위임한다.
    • 클래스간의 종속성이 약하다.
  • 이미 잘 만들어진 클래스를 재사용하기 위해서는 상속이 아닌 위임을 사용한다.
  • IS-A 관계가 아닌 클래스간의 상속은 HAS-A로 리팩토링 한다.

 

상속

상속은 좀 더 일반적인 클래스에서 그보다 구체적인 클래스가 여러개  생길 수 있는 경우에 사용한다.

상속을 통한 방법은 결합도가 강하기 때문에, 코드의 재사용의 목적으로는 사용하지 않는 것이 좋다.

 

 

 

리팩토링 전 - 학생 클래스가 과목 클래스를 상속한 경우

  • 처음엔 전공과목 하나만 있었지만, 점점 과목이 추가 됨.
  • 본문에 예시를 복붙하지는 않는데, 예시에서는 Subject 클래스의 값을 사용하려고 extends 받아서 구현하도록 되어 있었음.  이 관계에서 Student와 Subject 간의 관계는 IS-A 관계가 아니라 상속받아서 사용하는 것은 부적절하다.
  • 따라서 이런 경우 Has-A 관계로 구성하여 구현하는 것이 옳다. 

 

리팩토링 후 - Student 학생 클래스에서 Subject 클래스를 상속 받는 것이 아닌, 구성하여 사용하도록 리팩토링 함

 

 

package refactoringisawithhasa;

import java.util.ArrayList;

public class Student{
	
	private String studentName;
	private String studentId;
	
	private Subject majorSubject;
	private ArrayList<Subject> subjectList = new ArrayList<Subject>();
	
	public Student(String studentName, String studentId, String majorSubjectName, int majorCode) {
		this.studentName = studentName;
		this.studentId = studentId;
		this.majorSubject = new Subject(majorSubjectName, majorCode);
		subjectList.add(this.majorSubject);
	}
	
	public void addSubject(String subjectName, int subjectCode) {
		Subject subject = new Subject(subjectName, subjectCode);
		subjectList.add(subject);
	}
	
	public void setSubjectScore(int subjectCode, int score) {
		for(Subject subject : subjectList) {
			int code = subject.getSubjectCode();
			if(subjectCode == code) {
				subject.setScore(score);
				return;
			}
		}
		
		System.out.println("no subject");
	}
	
	public void getReport() {
		int total = 0;
		
		System.out.println(studentName + "님의 전공과목은 " + majorSubject.getSubjectName() + "이고, 점수는 : " + majorSubject.getScore() + "입니다.");
	
		for(Subject subject : subjectList) {
			System.out.println(subject.getSubjectName() + " : " + subject.getScore());
			total += subject.getScore();
		}
		
		System.out.println("total : " + total);
	}

	
}

 

 

package refactoringisawithhasa;

public class Subject {
	private String subjectName;
	private int subjectCode;
	private int score;
	
	public Subject(String subjectName, int subjectCode) {
		super();
		this.subjectName = subjectName;
		this.subjectCode = subjectCode;
	}
	public String getSubjectName() {
		return subjectName;
	}
	public void setSubjectName(String subjectName) {
		this.subjectName = subjectName;
	}
	public int getSubjectCode() {
		return subjectCode;
	}
	public void setSubjectCode(int subjectCode) {
		this.subjectCode = subjectCode;
	}
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
	
	

}

 

 

package refactoringisawithhasa;

public class Main {
	public static void main(String[] args) {
		Student studentLee = new Student("Lee", "12345", "국어국문", 100);
		Student studentKim = new Student("Kim", "67890", "영어영문", 200);
		
		studentLee.addSubject("수학",  300);
		studentLee.setSubjectScore(100, 90);
		studentLee.setSubjectScore(300, 100);
		
		studentKim.addSubject("수학",  300);
		studentKim.setSubjectScore(200, 100);
		studentKim.setSubjectScore(300, 70);
		
		studentLee.getReport();
		studentKim.getReport();
	}
}

댓글