-
Notifications
You must be signed in to change notification settings - Fork 1
Day 12(21.09.16)
※ 들어가기에 앞서
본 정리글은 수업의 진행대로 정리하고 있기에 내용에 따라 순서가 뒤죽박죽일 수 있습니다.
필드, 메소드를 하나로 묶고 실제 구현 내용을 감추는 것을 말한다. 외부 객체는 객체 내부의 구조를 알 수 없으며 객체가 겉으로 드러나서 제공하는 필드와 메소드만 제공할 수 있다. 쉽게 말하면 외부 객체에서는 캡슐화된 객체의 필드에 접근할 수 없단 얘기다.
이렇게 캡슐화를 통해 객체 정보를 보호하는 이유는 외부의 잘못된 사용으로 인해 객체가 손상되지 않도록 하기 위함이다. 예를 들어, 자동차의 중요 부품이 겉으로 드러나 충격 등의 외부적 요인에 의해 망가지지 않도록 차체 내부에 숨기는 것이나 마찬가지다. 이러한 캡슐화는 외부에서 접근을 허락할 것인가를 결정하기 위해 **접근 제한자(Access Modifier)**를 사용한다. 접근 제한자의 종류에는 private, default, protected, public이 있는데 이들에 대한 내용은 아래에 작성할 예정이다.
상속이란 일반적으로 부모가 가지고 있는 것을 자식에게 물려주는 것을 만한다. 객체 지양 프로그래밍에서도 부모 역할을 하는 상위 객체와 자식 역할의 하위 객체가 있는데, 상위 객체는 자신이 가지고 있는 필드와 메소드를 하위 객체에게 물려줄 수 있다. 이러한 상속은 상위 객체를 재사용하여 하위 객체를 쉽고 빠르게 설계할 수 있도록 도와주며, 이미 개발된 객체를 사용하는 것이므로 반복된 코드의 중복을 줄여준다. 또한, 상위 객체의 수정함으로서 하위 객체를 수정하는 효과가 있으므로 유지 보수 시간을 최소화시켜 주기도 한다.
같은 타입이지만 실행 결과가 다양한 객체를 이용할 수 있는 성질을 말한다. 프로그래밍 측면에서는 하나의 타입에 여러 객체를 대입하여 다양한 기능을 이용할 수 있도록 해주는 것이다. 자바에선 이를 위해 부모 클래스 또는 인터페이스의 타입 변환을 허용하고 있다. 부모 타입에는 모든 자식 객체가 대입될 수 있으며, 인터페이스 타입에는 모든 구현 객체가 대입될 수 있다. 예를 들어, 자동차 한대가 있을 때, 타이어라면 K 타이어든, H 타이어든 전부 사용할 수 있으나 성능이 다르게 나오는 것과 마찬가지이다.
생성자는 new 연산자와 같이 사용되며 클래스로부터 객체를 생성할때 호출되어 객체의 초기화를 담당한다. 여기서 객체의 초기화란 필드를 초기화하거나, 메소드를 호출해서 객체를 사용할 준비를 하는 것을 말한다. 이 생성자를 실행시키지 않고서는 객체를 만들 수 없으며, new 연산자로 객체가 생성되면 heap 영역에 객체가 생성되고, stack 영역에 객체의 주소가 리턴된다.
모든 클래스에는 하나 이상의 생성자가 반드시 존재한다.
클래스가 public class로 선언되면 기본 생성자에도 public이 붙지만, public 없이 class로만 선언된 클래스에는 기본 생성자에도 public이 붙지 않는다. public과 default 에 대한 얘기는 다음 파트에서 확인하기로 한다.
기본 생성자 대신 생성자를 명시적으로 선언하려면 다음과 같은 형태로 작성한다.
Class (Parameter 1, Parameter 2, ...) {
//객체의 초기화 코드
}생성자는 메소드와 비슷한 형태를 하고 있으나 리턴 타입이 없고, 클래스 이름과 동일하다. 생성자 블록 내부에는 객체 초기화 코드가 작성되는데, 일반적으로 필드의 초기값이나 메소드 호출 등의 객체 사용 전에 필요한 준비를 한다. 다음 예시를 보자.
Car myCar = new Car("Grandeur", "black", 300);위에서 Car 생성자를 호출할때 세 개의 값을 제공한다고 한다면, 다음과 같이 생성자를 선언해야 한다.
public class Car {
//생성자
Car(String model, String color, int maxSpeed)
}클래스에 생성자가 명시적으로 선언되어 있을 땐 반드시 선언된 생성자를 호출해서 객체를 생성해야만한다.
//Car.java
public class Car {
Car(String color, int cc) {
}
}//CarExample.java
public class CarExample {
public static void main(String[] args) {
Car myCar = new Car("black", 3000);
//Car myCar = new Car(); // 위에서 생성자가 명시적으로 선언되었기에 기본 생성자를 호출할 수 없다.관례적으로는 생성자의 매개변수로 필드와 동일한 이름을 갖는 매개변수를 사용하는데, 이 경우 필드와 매개 변수의 이름이 동일하기 떄문에 생성자 내부에서 필드에 접근할 수 없다. 동일한 이름의 매개 변수가 사용 우선순위가 높기 떄문인데, 이때의 해결 방법은 필드에 해당하는 변수 앞에 "this."을 붙이면 된다. 이는 객체가 자기 자신을 this라고 부르는 것으로 참조 변수로 필드를 사용하는 것과 동일하다.
main() 메소드를 가지지 않는 대부분의 클래스는 외부에서 이용할 목적으로 설계된 라이브러리 클래스이다. 이 라이브러리 클래스를 설계할 때엔 외부에서 접근할 수 있는 멤버와 접근할 수 없는 멤버로 구분해서 설계하는 것이 바람직하다. 이때 사용가능한 것이 바로 접근 제한자(Access Modifier)이다.
적용 대상 : 클래스, 필드, 생성자, 메소드
접근할 수 없는 클래스 : 없음
적용 대상 : 필드, 생성자, 메소드
접근할 수 없는 클래스 : 자식 클래스가 아닌 다른 패키지에 소속된 클래스
적용 대상 : 클래스, 필드, 생성자, 메소드
접근할 수 없는 클래스 : 필드, 생성자, 메소드
적용 대상 : 필드, 생성자, 메소드
접근할 수 없는 클래스 : 모든 외부 클래스
위와 같은 접근 제한자의 용도는 객체 외부에서 객체 데이터에 직접적으로 접근하는 것을 막기 위함이다. 그 이유는 객체의 데이터를 외부에서 마음대로 읽고 변경할 경우 객체의 무결성이 깨질 수 있기 때문이다. 예를 들어 자동차의 속력을 정할때 외부에서 -100이나 4250 같은 비정상적인 데이터를 입력할 경우 문제가 발생할 수 있기 때문이다. 이러한 문제점을 사전에 방지하고 해결하기 위해 객체 지향 프로그래밍에서는 메소드를 통해서 데이터를 변경하는 방법을 선호한다. 이러한 역할을 하는 메소드를 Setter라고 하는데, 자동차의 속도를 setSpeed() 메소드로 변경할 경우 입력되는 값에 조건을 부여할 수 있어 사전에 검증하는 과정을 거칠 수가 있다.
외부에서 객체의 데이터를 읽을 경우에도 별도의 메소드를 사용하는 것이 좋은데, 외부에서 객체의 필드 값을 사용하기에 부적절한 경우가 있기 때문이다. 예를 들면 킬로미터나 마일과 같이 단위가 다른 경우가 있는데, 이럴때 Getter 메소드를 사용하면 필드값을 안전하게 변경 및 사용할 수 있다.
Getter Setter 메소드 연습
result
color is Yellow
speed is 120