Chap 05. Java 클래스와 객체 (1) [Do it! 자바 프로그래밍 입문]

doriskim·2022년 11월 23일
0

*본 내용은 [Do it! 자바 프로그래밍 입문] 책과 강의를 보고 공부하면서 요점 정리한 내용입니다.

◼ 객체지향 프로그래밍

✔ 객체지향 프로그래밍 (Object Oriented Programming, OOP)

객체를 기반으로 하는 프로그래밍

✔ 절차지향 프로그래밍 (Procedural Programming)

순서대로 일어나는 일을 시간순으로 프로그래밍하는 것
예) C언어

◼ 클래스(class)

✔ 클래스

객체에 대한 속성과 기능을 코드로 구현 한 것

✔ 클래스의 속성

클래스의 특성(property), 속성(attribute), 멤버 변수(member variable)라고도 함
자료형을 이용하여 멤버 변수로 선언

✔ 클래스의 기능

클래스가 하는 기능들을 메서드(method)로 구현
멤버 함수(member function)라고도 함

✔ 클래스 정의하기

(접근 제어자) class 클래스 이름 {
	멤버 변수;
    메서드;
}    

✔ 학생 클래스의 예

속성: 학번, 이름, 학년, 사는 곳 등
기능: 수강신청, 수업듣기, 시험보기 등

package classpart;

public class Student{
	//멤버 변수(속성)
	int studentID;		//학번
    String studentName;	//학생 이름
    int grade;			//학년
    String address;		//사는 곳

	//메서드(기능)
	public void showStudentInfor(){				//이름, 주소 출력
    	System.out.println(studentName+","+address);	
    }
    public String getStudentName(){				//이름 가져오기
    	return studentName;
	}
	public void setStudentName(String name){	//이름 입력하기
    	studentName = name;
	}
}
  • 하나의 java 파일에 하나의 클래스를 두는 것이 원칙이나, 여러 개의 클래스가 같이 있는 경우 public 클래스는 단 하나이며, public 클래스와 자바 파일의 이름은 동일해야 함

  • 자바의 모든 코드는 class 내부에 위치
    외부엔 package 정의와 다른 class를 가져다 사용하는 import만 사용 가능

✔ 패키지(package)의 역할

  • 소스의 묶음
  • 패키지의 이름은 묶인 소스들의 성격을 나타낸다.
  • 패키지의 계층 구조를 만드는 작업은 소스 코드를 어떠한 계층 구조로 관리할지 구성하는 것이다.
  • 클래스의 전체 이름(class full name)은 '패키지이름.클래스이름'이다.
    클래스 이름이 같다고 해도 패키지 이름이 다르면 클래스 전체 이름이 다른 것이므로 다른 클래스가 된다.

◼ 메서드(method)

✔ 함수

하나의 기능을 수행하는 일련의 코드
중복되는 기능은 함수로 구현하여 함수를 호출하여 사용함

- 함수 정의하기
반환 값이 없는 경우 함수반환형에 void라고 작성

함수반환형 함수이름 (매개변수){
	...
	return예약어 ...;
}    

예시)

int add(int num1, int num2){
	int result;
    result = num1 + num2;
    return result;
}

✔ 메서드

메서드는 함수 중에서 클래스(객체)안에 구현된 함수를 메서드라고 한다.

- 메서드 구현 예시

package classpart;

public class Student{
	int studentID;		
    String studentName;	
    int grade;			
    String address;		

	//메서드(기능)
	public void showStudentInfor(){				//이름, 주소 출력
    	System.out.println(studentName+","+address);	
    }
    public String getStudentName(){				//이름 가져오기
    	return studentName;
	}
	public void setStudentName(String name){	//이름 입력하기
    	studentName = name;
	}
}

✔ 함수와 스택(stack) 메모리

스택(stack) - 함수가 호출될 때 지역변수들이 사용하는 메모리
함수의 기능 수행이 끝나면 자동으로 반환됨

◼ 클래스와 인스턴스

✔ new 예약어로 클래스 생성하기

클래스형 변수이름 = new 생성자;

이렇게 생성된 클래스를 '인스턴스'라고 한다.

✔ 클래스 사용과 main()함수

주로 방법2를 자주 사용

package classpart;

public class Student{
	int studentID;		
    String studentName;	
    int grade;			
    String address;		

	public void showStudentInfor(){				
    	System.out.println(studentName+","+address);	
    }
    public String getStudentName(){				
    	return studentName;
	}
	public void setStudentName(String name){	
    	studentName = name;
	}
    
    //방법1 - Student 클래스에 main()함수 추가하기
    public static void main(String[] args){
    	Student studentLee = new student();
        studentLee.studentName = "이순신";
        studentLee.studentID = 100;
        studentLee.address = "서울시 서초구 서초동";

		Student studentKim = new student();
        studentKim.studentName = "김유신";
        studentKim.studentID = 101;
        studentKim.address = "미국 산호세";
        
        studentLee.showStudentInfor();
    	studentKim.showStudentInfor();
    }
}
//방법2 - main()함수를 포함한 실행 클래스 따로 만들기
package classpart;

public class StudentTest{
	public static void main(String[] args){
    	Student studentLee = new student();
        studentLee.studentName = "이순신";
        studentLee.studentID = 100;
        studentLee.address = "서울시 서초구 서초동";

		Student studentKim = new student();
        studentKim.studentName = "김유신";
        studentKim.studentID = 101;
        studentKim.address = "미국 산호세";
        
        studentLee.showStudentInfor();
    	studentKim.showStudentInfor();
    }
}

✔ 인스턴스와 힙(heap) 메모리

[힙(heap)]

  • 프로그램에서 사용하는 동적 메모리 공간을 말함.
  • new 키워드로 인스턴스(객체)가 생성될 때 사용하는 공간.
  • 힙은 사용이 끝나면 메모리를 해제해 주어야 함. C나 C++에선 프로그래머가 직접 메모리를 해제해야 하지만 자바에서는 가비지 컬렉터가 자동으로 메모리를 해제해 줌.

하나의 클래스 코드로 부터 여러 개의 인스턴스를 생성하면 인스턴스는 힙 메모리에 생성됨. 이때 각각의 인스턴스는 다른 메모리에 다른 값을 가짐.

studentLee가 (ID, name, grade, address)의 위치를 저장하고 있음. 즉, studentLee가 힙 메모리의 주소값을 저장하고 있음.
'System.out.println(studentLee);'를 하면 'classpart.Student@16f65612'와 같은 주소값이 출력됨.
이때 studentLee를 참조 변수, 내부에 저장된 'classpart.Student@16f65612'와 같은 주소 값을 참조 값이라고 함.

*참조 변수: 메모리에 생성된 인스턴스를 가리키는 변수
참조 값: 생성된 인스턴스의 메모리 주소 값

◼ 생성자(constructor)

Student studentLee = new student();

new 예약어로 클래스를 생성할 때 작성한 다음 코드에서 student() 함수를 생성자라고 한다.
생성자는 class이름과 동일해야 한다.
생성자는 반환 타입이 없다.
생성자는 new 키워드로만 호출이 된다.

✔ 디폴트 생성자

package classpart;

public class Student{
	int studentID;		
    String studentName;	
    int grade;			
    String address;		
}

다음과 같은 Student 클래스 내부에 생성자가 따로 없다. 그래도 new Student()를 이용해 객체를 만들 수 있었다. 그 이유는 생성자가 없는 클래스는 클래스 파일을 컴파일할 때 자바 컴파일러에서 자동으로 생성자를 만들어주기 때문이다. 이렇게 자동으로 만들어 주는 생성자를 디폴트 생성자라고 한다.
디폴트 생성자는 매개변수도 없고 구현 코드도 없다. 프로그래머가 다음과 같이 디폴트 생성자를 직접 구현할 수도 있다.

package classpart;

public class Student{
	int studentID;		
    String studentName;	
    int grade;			
    String address;	
    
    public Student() {} //디폴트 생성자
}

✔ 생성자 만들기

인스턴스가 생성됨과 동시에 멤버 변수의 값을 지정하고 인스턴스를 초기화하고 싶을 때 생성자를 직접 구현하여 사용할 수 있다.

package classpart;

public class Student{
	int studentID;		
    String studentName;	
    int grade;			
    String address;	
    
    public Student(String name) { //이름을 매개변수로 입력받아 Student 클래스를 생성하는 생성자
    	studentName = name;
    } 
}

주의할 점은 생성자를 직접 구현한 경우엔 디폴트 생성자가 자동으로 만들어지지 않는다. 따라서 Student studentLee = new student();로 인스턴스를 생성하고 싶으면 디폴트 생성자를 다음과 같이 직접 추가해주어야 한다.

package classpart;

public class Student{
	int studentID;		
    String studentName;	
    int grade;			
    String address;	
    
    public Student() {} //디폴트 생성자 직접 추가
    
    public Student(String name) {
    	studentName = name;
    } 
}

위와 같이 클래스에 생성자가 두 개 이상 제공되는 경우를 생성자 오버로드라고 한다.

◼ 참조 자료형(reference data type)

✔ 참조 자료형

[변수의 자료형]

참조 자료형이란 클래스 형으로 선언하는 자료형으로 기존 Java JDK에서 제공되는 것을 사용할 수도, 사용자가 직접 만들어 사용할 수도 있다.

*참고
String과 같이 new 예약어가 필요없는 참조 자료형들이 있다.

✔ 참조 자료형의 예

학생의 속성 중 수업에 대한 부분
수업에 대한 각 속성을 학생 클래스에 정의하지 않고 수업이라는 클래스로 분리해서 사용
이때 과목은 참조 자료형으로 선언

Student.java

package reference;

public class Student {
	
	int studentID;
	String studentName;
	Subject korea;
	Subject math;
	
	public Student() {
		korea = new Subject("국어");
		math = new Subject("수학");
	}
	
	public Student(int id, String name) {
		studentID = id;
		studentName = name;
		
		korea = new Subject("국어");
		math = new Subject("수학");
	}
	
	public void setKorea(int score) {
		korea.setScore(score);
	}
	
	public void setMath(int score) {
		math.setScore(score);
	}
	
	public void showStudentInfo() {
		int total = korea.getScore() + math.getScore();
		System.out.println(studentName + " 학생의 총점은 " + total + "점 입니다.");
	}
}

Subject.java

package reference;

public class Subject {
	
	String subjectName;
	int score;
	
	public Subject(String name) {
		subjectName = name;
	}
 
	public void setSubjectName(String name) {
		subjectName = name;
	}
	
	public int getScore() {
		return score;
	}
	
	public void setScore(int score) {
		this.score = score;
	}
	
	public String getSubjectName() {
		return subjectName;
	}
}

StudentTest.java

package reference;

public class StudentTest {

	public static void main(String[] args) {
		Student studentJames = new Student(100, "James");
		studentJames.setKorea(100);
		studentJames.setMath(100);
		
		Student studentTomas = new Student(101, "Tomas");
		studentTomas.setKorea(80);
		studentTomas.setMath(60);
		
		studentJames.showStudentInfo();
		studentTomas.showStudentInfo();
	}

}

콘솔 창 결과

James 학생의 총점은 200점 입니다.
Tomas 학생의 총점은 140점 입니다.

◼ 정보 은닉(information hiding)

✔ 접근 제어자

접근 제어자설명
아무것도 없는 경우default이며 같은 패키지 내부에서만 접근할 수 있습니다.
public외부 클래스 어디에서나 접근할 수 있습니다.
private같은 클래스 내부에서만 접근할 수 있습니다.
protected같은 패키지 내부와 상속 관계의 클래스에서만 접근할 수 있고 그 외 클래스에서는 접근할 수 없습니다.

✔ private 접근 제어자

클래스의 외부에서 클래스 내부의 멤버 변수나 메서드에 접근(access)하지 못하게 하는 경우 사용
멤버 변수나 메서드를 외부에서 사용하지 못하도록 하여 오류를 줄일 수 있음
변수에 대해서는 필요한 경우 get(), set() 메서드를 제공

✔ 실습

BirthDayTest.java

package hiding;

class BirthDay {
	private int day; 
	private int month;
	private int year;
	
	public int getDay() {
		return day;
	}
	public void setDay(int day) {
		if(month==2) {
			if(day<1 ||day>28) {
				System.out.println("날짜 오류입니다.");
			}
		}
		else {
			this.day = day;
		}
	}
	public int getMonth() {
		return month;
	}
	public void setMonth(int month) {
		this.month = month;
	}
	public int getYear() {
		return year;
	}
	public void setYear(int year) {
		this.year = year;
	}
	
}

public class BirthDayTest{ //public 클래스 이름과 자바 파일 이름 같아야 함
	public static void main(String[] args) {
		
		BirthDay day = new BirthDay();
		
//		day.day = 30;	//private 이므로 오류 발생
//		day.month = 2;
//		day.year = 2018;
		
		//다음과 같이 날짜 설정해야 한다.
		day.setMonth(2);
		day.setDay(30); //public 매서드 통해 윤년 처리 
		day.setYear(2018);

	}
}

콘솔 창 결과

날짜 오류입니다.

※ 변수에 대해서 get은 가능하게 set은 불가능하게 하여 'read only'로 설정가능

◼참고

※ 명명법 정리

① 패키지
전부 소문자

② 클래스, 생성자
(Pascal 표기법)
대문자로 시작
단어 바뀌면 대문자

③ 변수, 함수
(Camel 표기법)
소문자로 시작
단어 바뀌면 대문자

※ 용어 정리(클래스, 인스턴스, 객체)

  • 클래스: 객체를 프로그래밍하기 위해 코드로 만든 상태
  • 인스턴스: 클래스가 메모리에 생성된 상태
  • 객체: 객체 지향 프로그램의 대상, 생성된 인스턴스, 클래스의 인스턴스

※ 이클립스 자동완성 기능: ctrl + space

※ get, set 메서드 빠르게 만들기

우클릭 > Source > Generate Getters and Setters... > 원하는 것 선택 후 Generate

0개의 댓글