객체의 상호작용
- 각 객체들은 독립적으로 존재하고 다른 객체와 상호작용하면서 동작한다.
- 방법 : 메소드를 호출하고 결과를 리턴받는다.
객체 간의 관계
- 상속 관계 : 상위 객체를 기반으로 하위 객체를 생성하는 관계 (예를 들면, 기계와 자동차)
- 사용 관계 : 다른 객체의 메소드를 호출하여 결과를 내는 관계 (예를 들면, 사람과 자동차)
- 집합 관계 : 부품과 완성품의 관계 (예를 들면, 타이어와 자동차)
객체와 클래스
- 클래스 : 객체를 생성하기 위한 필드와 메소드를 정의해놓은 곳
- 인스턴스 : 클래스로부터 만들어진 객체 (예를 들어, 자동차 객체는 자동차 클래스의 인스턴스이다)
- 인스턴스화 : 클래스로부터 객체를 만드는 과정
객체 지향 프로그래밍 개발 과정 3단계
1. 클래스 설계
2. 설계된 클래스를 통해 객체 생성
3. 생성된 객체 사용
* 주의할 점 : main() 메소드가 없는 클래스는 객체 생성 과정을 거쳐야 사용 가능함
클래스 선언
* 식별자 작성 규칙
- 하나 이상의 문자로 구성
- 숫자로 시작할 수 없음
- 특수문자로는 $ 와 _ 만 가능하다
- 키워드 사용 불가 (예를 들면, for, int 사용 불가)
- 되도록이면 첫 글자는 대문자, 나머지는 소문자, 카멜 표기법 이용
- 클래스 선언시 public 접근 제한자를 붙일때는 반드시 소스파일 이름과 동일한 클래스명을 사용해야함
객체 생성과 클래스 변수
public class Student {
int num = 0;
//생성자
Student() {
num = 100;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
}
public class StudentExample {
public static void main(String[] args) {
Student s1 = new Student(); // 객체 생성
System.out.println(s1.num); // 100
System.out.println("s1 변수가 Student 객체를 참조합니다.");
s1.setNum(1);
System.out.println(s1.getNum()); // 1
Student s2 = new Student(); // 객체 생성
System.out.println("s2 변수가 또 다른 Student 객체를 참조합니다.");
s2.setNum(2);
System.out.println(s2.getNum()); //2
}
}
** 생성자가 필요한 이유
- main 문이 돌때 가장 먼저 선언되어 값을 초기화하는 작업을 해줌
- 클래스에는 필드, 생성자, 메소드가 들어있음
- s1 객체와 s2 객체는 Student 클래스의 인스턴스이다.
- 비록 같은 클래스로부터 나온 것이지만 new 연산자를 사용했기 때문에 객체가 메모리에 각각 생성된다.
- 자신만의 고유 데이터를 가지면서 메모리에서 완전히 독립된 서로 다른 객체들이다.
객체 생성 구조
- s1 이라는 변수는 스택 영역에 메모리에 추가되고 그 변수는 힙 영역에 만들어진 Student 객체를 참조하게 된다.
- s2도 마찬가지 과정을 거치고 여기서 s2는 힙 영역에 이미 만들어진 Student 객체를 참조하는 것이 아니라
새로 하나 더 만들어서 참조하게 된다. (new 연산자를 사용했으므로)
두 클래스를 따로 생성해야하는 이유
- 각 클래스의 목적
Student 클래스 : 라이브러리용이다, 여러 개가 생성됨, 다른 클래스에서 이용할 목적으로 설계
StudentExample 클래스 : 실행용이다, 한 개만 생성됨, main 메소드를 제공함
- 사실 두 클래스를 하나에 몰아서 적어도 가능함
public class Student2 {
int num = 0;
//생성자
Student2() {
num = 100;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public static void main(String[] args) {
Student s1 = new Student();
System.out.println(s1.num); // 100
System.out.println("s1 변수가 Student 객체를 참조합니다.");
s1.setNum(1);
System.out.println(s1.getNum()); // 1
Student s2 = new Student();
System.out.println("s2 변수가 또 다른 Student 객체를 참조합니다.");
s2.setNum(2);
System.out.println(s2.getNum()); //2
}
}
- 그럼에도 두 클래스로 나누어 작성하는 이유
1. 가독성
100개의 클래스를 가진 파일 하나 vs 1개의 클래스를 가진 파일 100개 를 비교해보면 이 중 후자가 더 가독성이 좋다고 할 수 있는데 그 이유는 각 기능을 파일명으로 구분이 가능하고 코드 길이가 짧아지기 때문.
2. 유연성
협업하는 과정에서 여러 사람이 수정을 할 때 하나의 파일을 수정하는 것과 여러 파일로 나뉘어진 클래스들을 각각 나눠서 수정하는 것 중 후자가 더 유연하다고 할 수 있음.
또한 어차피 컴파일시 클래스 개수대로 생성이 되서 만들때부터 나누어서 생성해주는 것이 좋음
(참고 : [JAVA] 자바 파일 분할, 파일 나누어 코딩하는 방법 (tistory.com) )
클래스의 구성 멤버
- 필드 (Field) : 객체의 데이터가 저장되는 곳
변수와 차이점 : 변수는 생성자와 메소드 내에서만 사용되고 실행 종료 시 자동 소멸되지만 필드는 생성자와 메소드 전체에서 사용되며 객체가 소멸되지 않는 한 항상 존재
- 생성자 (Constructor) : 객체 생성 시 초기화 역할 담당
필드를 초기화하거나 메소드를 호출해서 객체를 사용할 준비를 한다.
new 연산자로 호출됨, 메소드와 비슷해보이지만 클래스 이름으로 되어있고 리턴 타입이 없다는 차이점을 보임
- 메소드 (Method) : 객체의 동작에 해당하는 실행 블록
필드를 읽고 수정하는 등 메소드 블록 내부 코드를 일괄적으로 실행한다.
다른 객체를 생성해서 여러 기능을 수행하기도 함
메소드 실행 과정은 보통 호출하는 곳에서 매개 값을 받아 실행을 돌려준 후 나온 결과 값을 리턴을 통해 다시 호출한 곳으로 돌려준다.
클래스 다이어그램 이론
[ UML ] 클래스 다이어그램(Class Diagram) 이론 (tistory.com)
'👨💻 2. 웹개발_Back end > 2-1 Java' 카테고리의 다른 글
[JAVA] 06-3 생성자 (0) | 2021.08.02 |
---|---|
[JAVA] 06-2 필드 (0) | 2021.08.02 |
[JAVA] 05-3 열거 타입 (0) | 2021.07.30 |
[JAVA] 05-2 다차원 배열 (0) | 2021.07.30 |
[JAVA] 05-2 배열 (0) | 2021.07.29 |
댓글