[Java] day10. 클래스와 객체 / 캡슐화 / 생성자
다들 객체까지는 예습하라고 했는데, 안했기 때문에 두렵다..
객체지향언어 OOP 제발 이해할 수 있길.
클래스
클래스는 서로 다른 자료형의 데이터들 을 사용자 개발자 ) 정의로 하나로 묶어 새로운 타입을 정의
배열과 달리 다른 자료형들의 값을 하나로 묶을 수 있음
다른 곳에서 클래스의 필드에 접근하기 위해 '.' (참조연산자)를 활용.
클래스 내부에는 메소드를 작성하지 않고 바로 변수를 선언할 수 도 있다.
이것을 전역변수( 필드 == 인스턴스 변수 == 속성)라고 부른다.
필드에 접근하기 위해서는 레퍼런스명.필드명 으로 접근한다.
' . '은 참조연산자 라고 하는데, 레퍼런스 변수가 참조하고 있는 주소로 접근한다는 의미를 가진다.
각 공간을 필드명으로 접근한다. (배열은 인덱스로 접근, 객체는 필드명으로 접근)
필드에 직접 접근 시 문제점
1. 잘못된 값이 대입될 수 있다.
2. 필드명이 변경되면 관련된 코드를 일일히 수정해야한다. ( 유지보수성 ↓)
해결 방법
필드에 직접 접근하지 않고 메소드를 이용하여 간접 접근하도록 하면
올바르지 않은 범위의 값으로 변경되는 것도 막을 수 있고,
필드 값의 변경이 발생하더라도 사용자는 코드를 변경하지 않아도 된다.
필드에 직접 접근을 제한하는 방식
접근 제한자
클래스 혹은 클래스의 멤버에 참조연산자로 접근할 수 있는 범위를 제한하기 위한 키워드이다.
1. public : 모든 패키지에 접근 허용
2. protected : 동일 패키지에 접근 허용. 단 상속관꼐에 있는 경우 다른 패키지에서도 접근 가능
3. default : 동일 패키지 내에서만 접근 허용. (작성하지 않는 것이 default)
4. private : 해당 클래스 내부에서만 접근 허용
구분 | 해당클래스내부 | 같은패키지내 | 후손클래스내 | 전체 | |
+ | public | O | O | O | O |
# | protected | O | O | O | |
~ | default | O | O | ||
- | private | O |
위에 네 가지 접근 제한자는 클래스의 멤버(필드, 메소드)에 모두 사용가능하다.
단, 클래스 선언 시 사용하는 접근 제한자는 public과 default만 사용 가능하다.
캡슐화(encapsulation)
선언한 필드대로 공간은 생성되어 있지만 직접 접근 못하고
public으로 접근을 허용한 메소드만 이용할 수 있도록 해놓은 것이다.
=> 캡슐화는 유지보수성 증가를 위해 필드에 직접 접근을 제한하고
public 메소드를 이용해서 간접적으로 접근하여 사용할 수 있도록 만든 기술로
클래스 작성 시 특별한 목적이 아닌 이상 캡슐화가 기본 원칙으로 사용되고 있다.
객체 지향 언어
객체 지향 언어란 ?
현실 세계 는 사물이나 개념처럼 독립되고 구분되는 각각의 객체 로 이루어져 있으며
발생하는 모든 사건들은 객체 간의 상호작용 이다
이 세계관을 프로그래밍 언어에 도입하여 만들어진 언어가 객체 지향 언어 이다
클래스(class) 란 ?
객체를 추상화 한 것으로 인스턴스를 생성 할 목적 으로 정의 해놓은 소스 코드 작성 단위
자바에서 객체를 구현하기 위한 매커니즘으로 클래스를 사용한다
객체의 할당
new 연산자와 생성자를 사용하여 객체 생성 시 heap 메모리 공간에 서로 다른 자료형의
데이터가 연속으로 나열 할당 된 인스턴스 공간
추상화 ( abstraction )란 ?
유연성을 확보하기 위해 구체적인 것은 제거한다는 의미
프로그램에서 필요한 공통점을 추출 하고 , 불필요한 공통점을 제거 하는 과정
캡슐화의 원칙에 일부 어긋나긴 하지만 매번 추상화를 하지 않아도 되는 객체도 존재한다.
행위 위주가 아닌 데이터를 하나로 뭉치기 위한 객체(Data Transfer Object)의 경우이다.
값 객체를 설계할 때는 행위가 아닌 데이터 위주이며, 캡슐화 원칙을 준수하려
모든 필드를 private로 직접 접근을 막고, 각 필드값을 변경하거나 반환하는 메소드를 세트로 미리 작성해둔다.
private 필드와 필드값을 수정하는 설정자(setter), 필드에 접근하는 접근자(getter)들로 구성된다.
private로 만들면 필드에 직접 접근이 제한되므로 public으로 접근을 허용하는
설정자/접근자를 통해 간접 접근할 수 있도록 한다.
설정자(setter) / 접근자(getter)의 경우 실무에서 암묵적으로 통용되는 작성 규칙이 존재한다.
설정자(setter) 작성규칙
: 필드값을 변경할 목적의 매개변수를 변결하려는 필드와 같은 자료형으로 선언하고,
호출 당시 전달되는 매개변수의 값을 이용하여 필드의 값을 변경한다.
[표현식]
public void set필드명(매개변수){
필드 = 매개변수;
}
[작성예시]
public void setName(String name) {
this.name = name;
}
접근자(getter) 작성규칙
: 필드의 값을 반환 받을 목적의 메소드 집합을 의미한다.
각 접근자는 하나의 필드에만 접근하도록 한다.
필드에 접근해서 기록된 값을 return을 이용하여 반환하며, 이 때 반환 타입은 반환하려는 값의 자료형과 일치시킨다.
[표현식]
public 반환형 get필드명() {
return;
}
[작성예시]
public String getName() {
return this.name;
}
/*boolean인 접근자는 get으로 시작하지 않고 is로 시작하는 것이 관례이다.*/
public boolean isActivated() {
return isActivated;
}
생성자 ( Constructor ) 란?
객체가 new 연산자 를 통해 Heap 메모리 영역에 할당될 때 1 회성으로 호출되는 리턴타입이 없는 메소드
인스턴스 생성 시 필드 초기화 목적 으로 주로 사용 된다
생성자 작성 규칙
생성자의 선언은 메소드 선언과 유사하지만 반환값이 없음
생성자명을 클래스명과 동일해야 함
* 지금까지 우리가 객체를 생성할 때
* 클래스명 래퍼런스변수 = new 클래스명(); 이라고 작성했으나
* new 뒤의 클래스명은 사실 생성자 (constructor)라 불리는 메소를 호출하는 구문이다.
* 정확히 말하자면 클래스명 레퍼런스변수 = new 생성자(); 라고 표현한다.*/
* 생성자란?
* 인스턴스를 생성할 때 초기 수행할 명령이 있는 경우 미리 작성해두고, 인스턴스를 생성할 때 호출된다.
* 생성자 함수에 매개변수가 없는 생성자를 기본 생성자( default constructor) 라고 하며,
* 기본 생성자는 컴파일러에 의해 자동으로 추가되었기 때문에 지금까지 명시적으로 작성하지 않고 사용할 수 있었다.
* -> 매개변수가 있는 생성자가 한 개라도 존재하는 경우 컴파일러는 기본 생성자를
* 자동으로 추가해주지 않으니 주의!
*
* 기본 생성자를 통해 인스턴스를 생성하게 되면 자료형별 초기값을 이용해 필드를 초기화 한다.
* 필드의 초기값을 사용자가 원하는대로 설정하고 싶은 경우 생성자의 호출 시
* 인자로 값을 전달하여 호출할 수 있다.
* 이러한 인자를 받아 필드를 초기화 할 목적의 생성자를 매개변수가 있는 생성자 라고 한다.
* *
생성자의 작성위치
작성 위치는 문법적으로 클래스 내부에 작성하면 되지만,
통상적으로는 필드 선언부와 메소드 선언부 사이에 작성하는 것이 관례이다.
생성자의 사용목적
- 인스턴스 생성 시점에 수행할 명령이 있는 경우 사용한다.
- 매개변수 있는 생성자의 경우 매개변수로 전달받은 값으로 필드를 초기화하며
인스턴스를 생성할 목적으로 주로 사용된다. - 작성한 생성자 외에는 인스턴스를 생성하는 방법을 제공하지 않는다는 의미를 가진다.
따라서, 인스턴스를 생성하는 방법을 제한하기 위한 용도로 사용할 수도 있다. (초기값 전달 강제화)
생성자 작성 방법
[표현식]
접근제한자 클래스명(매개변수) {
인스턴스 생성 시점에 수행할 명령기술 (주로 필드 초기화);
this.필드명 = 매개변수; //설정자(setter) 여러 개의 기능을 한 번의 호출로 수행할 수 있다.
}
this 는 인스턴스가 생성되었을 때 자신의 주소를 저장하는 래퍼런스 변수이다.
지역변수와 전역변수의 이름이 동일한 경우 지역변수를 우선적으로 접근하기 때문에
전역변수에 접근하기 위해서 this. 을 명시해야 한다.