클래스를 만나고 점점 만나는 개념들이 많아지고 있다. 이전 글의 상속은 객체지향의 핵심이며 객체지향 4대 특징 중 하나이다. 객체지향 4대 특징은 다음과 같다.
1. 추상화
2. 캡슐화
3. 상속
4. 다형성
왜 갑자기 객체지향 4대 특징 타령일까? 이번에 이야기할 접근 지정자는 캡슐화의 짝꿍인 정보은닉과 관련 있기 때문이다. 객체지향 4대 특징을 설명해줄 것이라고 기대했다면 어림도 없다.
캡슐화
간단하게 캡슐화를 설명하면 어떤 객체가 어떤 목적을 수행하기 위한 데이터(멤버 변수)와 기능(메서드)을 적절하게 모으는 것이다.
예를 들어 이름과 나이만 알고 먹고 자고 코딩만 하면 되는 개발자 객체를 캡슐화한다고 해보자.
class Developer {
String name;
int age;
eat() { print('eat'); }
sleep() { print('sleep'); }
coding() { print('This is not bug. It's just feature.'); }
}
이런 식으로 하나의 기능을 수행하는 객체를 만드는 것이 캡슐화이다.
추상화와 뭐가 다르지? (이렇게 추상화까지 설명하게 되고...)
추상화
추상화는 어떤 객체의 공통된 데이터와 메서드를 묶어서 이름(클래스명)을 부여하는 것이다. 이렇게 말하면 무슨 말인가 싶을 텐데 단순히 말하면 클래스를 만드는 일이다. 생각해보자. 사람 클래스를 만들 것이다. 사람 객체에는 남자도 있고 여자도 있고 학생도 있고 선생님도 있고 개발자도 있다.
이런 다양한 하위 객체들을 아우르는 사람을 의미하는 Person 클래스를 만들기 위해서 고민해야 하는 것은 무엇인가? 일단 모든 사람들이 공통적으로 갖는 데이터와 행동을 떠올려야 한다. 대충 생각해보자.
class Person {
String name;
int age;
eat() { }
sleep() { }
}
일단 사람이라면 이름과 나이가 있고 먹고 잔다. 이런 공통 속성을 추출해나가는 과정을 추상화라고 한다.
추상화를 잘한다면 앞선 Developer 클래스를 만들 때 Person 클래스를 상속받는 구조를 통해 중복된 부분을 많이 없앨 수 있다. 코드 재사용률을 높일 수 있다는 것이다.
다시 본론으로 돌아와서 그럼 캡슐화 중에 정보은닉은 무엇일까? 그건 먼저 접근 지정자를 알아보고 다음 글에서 getter, setter 개념을 살펴본 후 이야기할 문제다.
접근 지정자
접근 지정자는 클래스의 멤버 변수 또는 메서드 앞에 선언되고 종류에 따라 해당 멤버들에게 접근할 수 있는 범위가 달라진다.
자바의 경우에는 네 가지 접근 지정자가 존재한다. 그중에 private라는 접근 지정자는 동일 클래스 내에서만 접근이 가능하다. 그리고 public은 접근 범위에 제한 없이 모든 곳에서 접근 가능하다.
다트의 접근 지정자는 딱 두 종류다. 바로 앞서 말한 private와 public이다. 그러나 주의할 점이 있다! 접근 범위가 자바와 다르다. 다트에서 private 멤버의 접근 범위는 동일 클래스가 아니라 라이브러리(=자바 기준으로 패키지)이다.
또한 접근 지정자의 키워드도 다르다. 다트는 기본적으로 아무런 키워드가 없을 경우 public이다. private로 선언하기 위해서는 변수나 메서드 앞에 _(밑줄)을 붙여야 한다. 즉 기본 형태는 다음과 같다.
class Person {
String name;
int _age;
eat() { print('eat'); }
_sleep() { print('sleep'); }
}
_가 붙은 _age와 _sleep()은 private이고 name과 eat()는 public이다.
다음 예제를 통해서 실제로 접근 지정자의 동작을 확인할 수 있다.
Person 클래스를 main.dart가 아닌 외부의 Person.dart에 선언했다. main.dart에서 Person.dart를 import 하고 public 메서드인 eat()를 호출한다. 이때는 정상적으로 호출이 되어 eat가 출력이 된다. 하지만 주석 처리된 _sleep()을 호출하면 에러가 발생한다. private인 _sleep()은 main.dart에서 접근이 불가능하기 때문이다.