5-1. 객체 지향 프로그래밍과 클래스
클래스란?
객체의 속성과 기능을 코드로 구현한 것이다. 클래스를 정의하려면 클래스 이름과 클래스가 가지는 속성 또는 특성이 필요하다.
package classpart;
public class Student{ //class->클래스를 만드는 예약어, Student-> 클래스 이름
int studentID; //학번 (멤버변수)
String studentName; //학생이름(멤버변수)
int grade; //학년 (멤버변수)
String address; //사는곳 (멤버변수)
}
* 클래스 이름짓는 규칙 : 클래스 이름은 대문자로 시작한다. 소문자로 시작한다고 해서 오류가 발생하는 것은 아니지만 대문자로 시작하는 것이 개발자들 사이의 규칙이다.
5-2. 클래스 살펴보기
클래스 속성을 구현하는 멤버 변수
속성 | 자료형 | 변수 이름 | 설명 |
학번 | int | studentID | 학번은 정수로 나타낼 수있기에 int형으로 선언한다. |
이름 | String | studentNzame | 학생 이름은 문자로 되어있다. 그런데 이름은 하나의 문자가 아니라 여러 개의 문자로 이루어진 문자열로 표현한다. |
학년 | int | grade | 학년은 정수로 나타낼 수 있기 때문에 int형으로 선언한다. |
사는 곳 | String | address | 문자열을 나타내기 위해 String을 사용한다. |
클래스 기능을 구현하는 메서드
지금까지 클래스를 선언하고 클래스 속성인 멤버 변수를 선언했다. 그런데 클래스에서는 학생 객체가 가지는 속성을 사용해 학생과 관련된 기능을 구현할 수 있다. (ex, '학생에게 이름을 부여한다', '학생이 사는 곳을 출력한다') 이렇게 클래스 내부에서 멤버 변수를 사용하여 클래스 기능을 구현한 것을 '멤버 함수'또는 '메서드'라고 한다.
public class Student {
int studentID;
String studentName;
int grade;
String address;
public void showStudentInfo() { //메서드 추가
System.out.println(studentName + "," + address);
}
}
패키지란?
패키지는 클래스 파일의 묶음이다. 패키지를 만들면 프로젝트 하위에 물리적으로 디렉터리가 생성된다. 또한 패키지는 계층구조를 가질 수 있다. 프로젝트를 수행할 때 패키지의 계층 구조를 구성하는 것은 전체 프로젝트의 소스 코드를 어떻게 관리할지와 관련이 있다.
5-3. 메서드
함수란?
'하나의 기능을 수행하는 일련의 코드'이다.
함수 정의하기
int add (int num1, int num2){
int result;
result = num1 + num2;
return result;
}
함수 호출하고 값 반환하기
package classpart;
public class FunctionTest{
public static void main(String[] args) {
int num1 = 10;
int num2 = 20;
int sum = add(num1, num2); //add() 함수 호출
System.out.println(num1 + " + " + num2 + " = " + sum + "입니다");
}
public static int add(int n1, int n2){
i result = n1 + n2;
return result; //결과값 반환
}
}
클래스 기능을 구현하는 메서드
지금까지 설명한 함수는 오래전에 출시된 많은 프로그래밍 언어에서 이미 사용하고 있는 중요한 코드 구현 방법 중 하나이다. 자바 프로그램에는 클래스 내부에서 사용하는 멤버 함수가 있다. 이를 메서드(method)라고 하는데 메서드는 멤버 변수를 사용하여 클래스의 기능을 구현한다. 즉 메서드는 함수에 객체 지향 개념이 포함된 용어로 이해하면 된다.
public class Student {
int studentID;
String studentName;
int grade;
String address;
public String getStudentName() { //학생이름을 반환하는 메서드
return studentName;
}
//...
public void setStudentName(String name) { //학생 이름을 매개변수로 전달
studentName = name;
}
}
5-4. 클래스와 인스턴스
클래스 사용과 main() 함수
위에 만든 클래스를 직접 사용하여 결과를 출력해보자.
프로그램을 시작하는 main()함수
main() 함수에서 클래스를 사용하는 방법은 두 가지가 있다. 하나는 우리가 만든 클래스 내부에 main() 함수를 만드는 것이고, 또 하나는 외부에 테스트용 클래스를 만들어 사용하는 것이다.
Student 클래스에 main() 함수 포함하기
public class Student {
int studentID;
String studentName;
int grade;
String address;
public String getStudentName() {
return studentName;
}
public static void main(String[ ] args) { //main() 함수
Student studentAhn = new Student();
studentAhn.studentName = "김상민";
System.out.println(studentAhn.studentName);
System.out.println(studentAhn.getStudentName());
}
}
출력결과
김상민
김상민
main() 함수를 포함한 실행 클래스 따로 만들기
public class StudentTest {
public static void main(String[] args) { //main 함수
Student studentAhn = new Student(); //student 클래스 생성
studentAhn.studentName = "김상민";
System.out.println(studentAhn.studentName);
System.out.println(studentAhn.getStudentName());
}
}
클래스 이름이 같아도 패키지가 다르면 다른 클래스이다.
new 예약어로 클래스 생성하기
클래스를 사용하려면 먼저 클래스를 생성해야 한다. 자바에서 클래스를 생성할 때는 new 예약어를 사용하고 이어서 생성자를 써 준다. 클래스 자료형 변수를 선언하고 new 예약어로 생성자를 호출하여 대입하면 새로운 클래스가 생성된다. 클래스가 생성된다는 것은 클래스를 실제 사용할 수 있도록 메모리 공간을 할당받는 뜻이다. 이렇게 실제로 사용할 수 있도록 생성된 클래스를 '인스턴스'라고 한다. 그리고 그 인스턴스를 가리키는 클래스형 변수를 '참조 변수'라고 한다.
//(클래스형) (변수 이름) = (new) (생성자);
Student studentAhn = new Student();
위 코드는 Student 클래스 자료형으로 studentAhn 변수를 선언하고 new Student();로 Student 클래스를 생성하여 studentAhn에 대입한다는 뜻이다. 이때 studentAhn을 참조 변수라고 하고, 이 변수가 생성된 인스턴스를 가리킨다.
인스턴스와 참조 변수
객체, 클래스, 인스턴스
객체란 '의사나 행위기 미치는 대상'이며 이를 코드로 구현한 것이 클래스 이다. 그리고 클래스가 메모리 공간에서 생성된 상태가 인스턴스이다. 또한 생성된 클래스의 인스턴스를 객체라고도 한다. 클래스의 생성자를 호출하면 인스턴스가 만들어진다. 인스턴스는 여러 개 생성할 수도 있다.
인스턴스 여러 개 생성하기
public class StudentTest1 {
public static void main(String[] args) {
Student student1 = new Student(); //첫 번째 학생 생성
student1.studentName = "김상민";
System.out.println(student1.getStudentName());
Student student2 = new Student(); //두 번째 학생 생성
student2.studentName = "김상진";
System.out.println(student2.getStudentName());
}
}
출력결과
김상민
김상진
참조 변수 사용하기
Student student1 = new Student(); //멤버변수 사용
student1.studentName = "김상민"; //메서드 사용
5-5. 생성자
생성자란?
package constructor;
public class Person {
String name;
float height;
float weight;
}
package constructor;
public class PersonTest {
public static void main(String[] args) {
Person personLee = new Person(); //생성자
}
}
위 예제에서 자바에서 클래스를 생설할 때 사용하는 Person() 같은 함수를 생성자라고 한다. 클래스의 멤버 변수는 메서드에 의해 값이 변경될 수도 있지만, 처음 클래스를 생성할 때 값을 정해야 하는 경우도 있다. 생성자가 하는 일은 클래스를 처음 만들 때 멤버 변수나 상수를 초기화 하는 것이다.
디폴트 생성자
생성자는 클래스를 생성할 때만 호출한다. 생성자 이름은 클래스 이름과 같고, 생성자는 반환 값이 없다. 그런데 Person 클래스를 살펴보면 Person() 생성자가 따로 없다. 생성자가 없는 클래스는 클래스 파일을 컴파일할 때, 자바 컴파일러에서 자동으로 생성자를 만들어주는 생성자를 디폴트 생성자라고 한다. 디폴트 생성자는 매개변수가 없고 구현 코드도 없다.
package constructor;
public class Person {
String name;
float height;
float weight;
public Person() {}
}
생성자 만들기
생성자 만들기
package constructor;
public class Person {
String name;
float height;
float weight;
//사람 이름을 매개변수로 입력받아서 Person 클래스를 생성하는 생성자
public Person(String pname) {
name = pname;
}
}
생성자 테스트하기
package constructor;
public class PersonTest {
public static void main(String[] args) {
Person personLee = new Person();
}
}
결과는 오류가 발생한다. 오류가 난 이유는 생성자를 직접 구현하여 디폴트 생성자가 없기 때문이다. 자바 컴파일러는 생성자가 하나도 없는 경우에만 디폴트 생성자를 제공한다. 프로그래머가 생성자를 직접 추가하면 디폴트 생성자는 만들어지지 않는다.
디폴트 생성자 직접 추가하기
package constructor;
public class Person {
String name;
float height;
float weight;
public Person() {} //디폴트 생성자 직접 추가
public Person(String pname) {
name = pname;
}
}
생성자 오버로드
public class Student(){
int studentID;
//학번을 매개변수로 입력받아 Student 클래스를 생성하는 생성자
public Student(int studentID){
this.studentID = studentID;
}
}
학생이 생성될 때는 반드시 학번이 있어야 한다면 다음처럼 생성자를 제공할 수 있습니다.
생성자 사용하기
package constructor;
public class Person {
String name;
float height;
float weight;
public Person() {}
public Person(String pname) {
name = pname;
}
public Person(String pname, float pheight, float pweight) {
name = pname;
height = pheight;
weight = pweight;
}
}
테스트 클래스 구현하기
package constructor;
public class PersonTest {
public static void main(String[] args) {
// 디폴트 생성자로 클래스 생성한 후 인스턴스 변수 값을 따로 초기화
Person personKim = new Person();
personKim.name = "김상민";
personKim.weight = 85.5F;
personKim.height = 180.0F;
// 인스턴스 변수 초기화와 동시에 클래스 생성
Person personLee = new Person("이순신", 175,75);
}
}
5-6. 참조 자료형
참조 자료형이란?
학생 클래스 만들기(1)
package reference;
public class Student1 {
int studentID;
String studentName;
int KoreaScores;
int mathScore;
}
학생 클래스 만들기(2)
package reference;
public class Student2 {
int studentID;
String studentName;
int KoreaScores;
int mathScore;
String koreaSubject; //과목추가
String mathSubject; //과목추가
}
구현하고보니 이상한 점이 있다. 이 클래스는 학생에 대한 클래스인데 과목에 대한 변수가 계속 늘어나고 있다. 이 문제를 해결하기 위해 과목의 이름과 성적을 Subject라는 클래스로 분리하고, 학생에 Subject 변수를 각 과목별로 추가해보자.
과목 클래스 만들기
package reference;
public class Subject {
String SubjectName;
int scorePoint;
}
학생 클래스 만들기(3)
package reference;
public class Student3 {
int studentID;
String studentName;
Subject korean; //Subject형을 사용하여 선언
Subject math; //Subject형을 사용하여 선언
}
이렇게 구현하면 무엇이 달라질까? 기존의 Student2 클래스에서 과목 이름을 추가해야 한다면, koreaSubjectName, mathSubjectName 이렇게 두 개의 변수를 추가해야할 것이다. 하지만 Subject로 클래스를 분리하면 subjectName은 Subject 클래스에 선언하면 된다. 그리고 과목이름은 korean.subjectName으로 사용하고, 수학 과목 이름은 math.subjectName으로 사용할 수 있어 편리하다.
5-7. 정보 은닉
접근 제어자 살펴보기
객체 지향 프로그램에서는 예약어를 사용해 클래스 내부의 변수나 메서드, 생성자에 대한 접근 권한을 지정할 수 있다. 이러한 예약어를 '접근 제어자'라고 한다. public이라고 선언한 변수나 메서드는 외부 클래스에서 접근이 가능하며 외부 클래스가 사용할수 있다는 뜻이다. 반대로 접근 제어자를 private으로 선언한 변수나 메서드는 외부 클래스에서 사용할 수 없다.
private 사용하기
package hiding;
public class Student {
int studentID;
private String studentName; //studentName 변수를 private로 선언
int grade;
String address;
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
}
private 변수 테스트하기
package hiding;
public class StudentTest {
public static void main(String[] args) {
Student studentLee = new Student();
studentLee.studentName = "김상민";
System.out.println(studentLee.getStudentName());
}
}
결과는 오류가 발생한다. private 선언 때문에 참조할 수 없기 때문이다.
get(), set() 메서드
그렇다면 private로 선언한 studentName 변수를 외부코드에서 사용하려면 어떻게 해야할까? studentName 변수를 사용할 수 있도록 public 메서드를 제공해야 한다. public 메서드가 제공되지 않는다면 studentName 변수에 접근할 수 있는 방은 없다. 이때 사용할 수 있는 것이 get(), set() 메서드이다.
get(), set() 메서드 사용하기
package hiding;
public class Student {
int studentID;
private String studentName; //studentName 변수를 private로 선언
int grade;
String address;
//private 변수인 studentName에 접근해 값을 가져오는 public get() 메서드
public String getStudentName() {
return studentName;
}
//private 변수인 studentName에 접근해 값을 지정하는 public set() 메서드
public void setStudentName(String studentName) {
this.studentName = studentName;
}
}
private 변수에 접근하기
package hiding;
public class StudentTest {
public static void main(String[] args) {
Student studentLee = new Student();
//studentLee.studentName = "김상민";
//setStudentName() 메서드를 활용하여 private 변수에 접근
studentLee.setStudentName("김상민");
System.out.println(studentLee.getStudentName());
}
}
'객체 지향 프로그래밍 > Java' 카테고리의 다른 글
chapter 6. 클래스와 객체2 (0) | 2022.03.12 |
---|---|
chapter 9. 추상 클래스 (0) | 2022.03.11 |
chapter 4. 제어 흐름 이해하기 (0) | 2022.02.23 |
chapter 3. 자바의 여러 가지 연산자 (0) | 2022.02.23 |
chapter 2. 변수와 자료형 (2) | 2022.02.23 |
댓글