[그린컴퓨터] Server/JAVA(객체 지향 프로그래밍)

참조 자료형 {참조 자료형이란, 헷갈렸던 점(전반부), 헷갈렸던 점(후반부), 추가 이해 자료}

Ben의 프로그램 2023. 5. 17. 23:55
728x90

참조 자료형이란?

  • 크기가 정해진 기본 자료형(int, char, float, double 등) 으로 선언하는 변수 뿐만 아니라 클래스 자료형으로 선언하는 참조 자료형 변수가 있다.
  • 예를 들어보면서 알아보겠습니다.
  • 어떤 학생이 국어와 수학 과목을 수강하는데, 시험을 본 후 국어 성적과 수학 성적 정보를 저장하는 프로그램을 만들려고 합니다. 
  • 객체 지향 프로그래밍을 시작할 때는 일단 클래스를 어떻게 만들지 생각해야합니다. 
package reference;

public class Student1 {
	int studentID;
	String studentName;
	int koreaScore;
	int mathScore;
}
  • 위의 예제에는 String 이 JDK(Java Development Kit)에서 제공하는 참조 자료형입니다. 
  • 나머지 변수는 기본 자료형입니다.
  • 그런데, 다음과 같은 경우가 있을 수 있습니다.
  • 성적을 저장하는 변수가 두 개 있는데, 만약 성적뿐만 아니라 이 학생이 수강하는 과목의 이름도 함께 저장해야 한다면 어떻게 할까요? 지금까지 아는 방법으로는 String 을 사용해서 과목 이름 변수까지 추가할 수 있습니다.
package reference;

public class Student2 {
	int studentID;
	String studentName;
	int koreaScore;
	int mathScore;
	String koreaSubject;
	String mathSubject;
}
  • 이렇게 구현하고 보니, 맘에 들지 않습니다. 
  • 왜냐하면, 이 클래스는 student 클래스인데도 불구하고 과목에 대한 변수가 생겨났기 때문입니다.
  • 이 문제를 해결하기 위해 과목의 이름과 성적을 Subject 라는 클래스로 분리하고, 학생에 Subject 변수를 각 과목별로 추가해 보겠습니다.
package reference;

public class Subject {
	String subjectName;
	int scorePoint;
}
package reference;

public class Student3 {
	int studentID;
	String studentName;
	Subject korean;
	Subject math;
}
  • 과목을 의미하는 Subject라는 클래스를 만들었습니다. 
  • Subject 클래스는 과목의 이름과 점수를 멤버 변수로 가지고 있습니다.
  • 또한 Student 클래스는 Subject 클래스를 멤버 변수로 가지면 됩니다.
  • 이것을 그림으로 표현하면 다음과 같습니다.

  • 이렇게 구현하면 달라지는 것이 무엇일까요?
  • 기존의 Student2 클래스에 과목 이름을 추가해야 한다면, koreanSubjectName, mathSubjectName 이렇게 두 개의 변수를 추가해야 할 것입니다. 하지만 Subject로 클래스를 분리하면 subjectName 은 Subject 클래스에 선언하면 됩니다.

헷갈렸던 점 (전반부)

  • 참조 자료형을 만든 다음, 참조 자료형 안에 담겨 있는 멤버 변수와 멤버 메소드를 어떻게 사용하는 것인지 헷갈렸다.
  • 특히, main 함수를 별도의 test 파일을 만들어서 실행시킬 때를 연습했는데, 처음에는 이게 어떻게 해야 작동하는지 잘 이해하지 못했다
  • 아래 코드는 내가 이해한 것들을 바탕으로 연습하면서 작성한 코드다. 총 3개 파일로 구성되어 있다. 
package reference;

public class Student3 {
	int studentID;
	String studentName;
	Subject korean;
	Subject math;
	
	public Student3(int id, String name) {
		studentID = id;
		studentName = name;
	}
	
	public void showStudent3Info() {
		System.out.println("학번 : " + this.studentID);
		System.out.println("이름 : " + this.studentName);	
		System.out.println("과목명 :" + this.korean.subjectName);
		System.out.println("점수 :" + this.korean.scorePoint);
		System.out.println("과목명 :" + this.math.subjectName);
		System.out.println("점수 :" + this.math.scorePoint);
	}
}
package reference;

public class Subject {
	String subjectName;
	int scorePoint = 0;
	
	public Subject(String name, int score) {
		subjectName = name;
		scorePoint = score;
	}
}
package reference;

public class StudentTest1 {

	public static void main(String[] args) {
		Student3 kimStudent3 = new Student3(2017105249, "KIM Byung");
		kimStudent3.korean = new Subject("korean", 80);
		kimStudent3.math = new Subject("math", 80);
		
		kimStudent3.showStudent3Info();
	}
    
}
  • 생성자와 참조 자료형을 활용하여 객체 지향 프로그램을 하나 만들었다.

헷갈렸던 점 (후반부)

  • 나는 Student3 클래스의 인스턴스인 Kim를 우선 만들고, Kim 안에 Subject 의 인스턴스인 math 와 korean 을 생성하는 순서로 작성했다. 이 순서를 그림으로 표현하면 아래와 같다.
Student3 Kim [인스턴스 생성]
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
kim.math = new Subject [인스턴스 생성]
  • 이런 방식으로 내가 코드를 작성했던 이유를 생각해 보자면, 지금 예시가 학생과 학생의 성적이다 보니까, 모든 경우가 고유한 케이스이고 그에 따라서 재사용을 전혀 염두에 두지 않고 작성을 해서 그렇게 생각을 했다. 
  • 무슨 말이냐면, 학생A 가 수학 80점을 받았다. 이것을 나는 아주 고유한 일이라고 생각했는데, 그렇지 않고 학생B가 수학 80점을 받았다면 수학 80점을 받은 그 자체가 재사용이 가능한 것이다
  • 이런 점을 고려하면 다음과 같이 코드를 수정할 수 있었다.
package reference;

public class Subject {
	String subjectName;
	int scorePoint;
	
	public Subject(String subjName, int scorePoint) {
		this.subjectName = subjName;
		this.scorePoint = scorePoint;
	}
}
package reference;

public class Student3 {
	int studentID;
	String studentName;
	Subject korean;
	Subject math;
	
	public Student3(int studentId, String studentName, Subject korean, Subject math) {
		this.studentID = studentId;
		this.studentName = studentName;
		this.korean = korean;
		this.math = math;
	}

	@Override
	public String toString() {
		return "Student3 [studentID=" + studentID + ", studentName=" + studentName + ", korean=" + korean + ", math="
				+ math + "]";
	}
	
	
}
package reference;

public class StudentTest1 {

	public static void main(String[] args) {
		Subject math = new Subject("math", 80);
		Subject korean = new Subject("korean", 75);
		Student3 kim = new Student3(2011102546, "Kim Byungsun", korean, math);
		System.out.println(kim.toString());
		
		Student3 kim2 = new Student3(2011102546, "Kim2 Byungsun", korean, math); //korean 과 math 는 kim 과 kim2 가 동일하므로 해당 참조변수를 그대로 상요하면 된다.
		System.out.println(kim2.toString());
		
		Subject math2 = new Subject("math", 70);
		Subject korean2 = new Subject("korean", 75);
		Student3 kim3 = new Student3(2011102546, "Kim3 Byungsun", korean2, math2);
		System.out.println(kim3.toString());
	}

}
  • StudentTest1 클래스에서 kim 과 kim2 인스턴스는 math 라는 Subject 의 인스턴스를 동일하게 가져가도 문제가 없다.
  • 이런 경우 kim2 는 kim 이전에 만들어 두었던 math 와 korean을 그대로 사용하면 된다. 
  • 참조 자료형을 먼저 만들어야 하므로 생성의 순서도 위와 달리 아래의 그림과 같이 바뀌었다.
Subject math = new Subject("math", 80);        
Subject korean = new Subject("korean", 75);
[참조 자료형의 인스턴스 먼저 생성]
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
Student3 kim = new Student3(2011102546, "Kim Byungsun", korean, math);
[참조 자료형을 멤버 변수로 갖는 클래스의 인스턴스를 나중에 생성]

추가 이해 자료

  • 이해를 돕기 위해 추가 실습 자료를 만들었습니다.
package reference.quiz;

class Department {
	String boss;
	String researcher;
	String headResearcher;
	
	public Department(String boss, String researcher, String headResearcher) {
		super();
		this.boss = boss;
		this.researcher = researcher;
		this.headResearcher = headResearcher;
	}
	
	
}

class Employee {
	String name;
	int age;
	int wage;
	int workingYear;
	Department managing;
	
	public Employee(String name, int age, int wage, int workingYear, Department managing) {
		super();
		this.name = name;
		this.age = age;
		this.wage = wage;
		this.workingYear = workingYear;
		this.managing = managing;
	}

	@Override
	public String toString() {
		return "Employee [name=" + name + ", age=" + age + ", wage=" + wage + ", workingYear=" + workingYear
				+ ", managing=" + managing + "]";
	}	
	
}
public class Quiz2 {

	public static void main(String[] args) {
		Department managing = new Department("경영 보스", "경영 연구원", "경영 수석 연구원");
		Employee shin = new Employee("SHIN HANBEEN", 26, 5000000, 10, managing);
		System.out.println(shin.toString());

	}

}