대표적으로 2가지가 있습니다.
자바에는 총 4가지의 접근 제어자가 존재합니다.
간단한 예제
public class SomeClass {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
// setter 메소드에서 데이터 유효성 체크
public void setName(String name) {
// null check
if(name == null) this.name = "test";
// length check
else if(name.length() > 5) this.name = name.substring(5);
// else
else this.name = name;
}
}
public class Main {
public static void main(String[] args) {
SomeClass some = new SomeClass();
some.setId(123);
some.setName("some");
System.out.println(cap.getId());
System.out.println(cap.getName());
}
}
정보 은닉의 목적
대표적인 정보은닉
// 동물을 나타내는 추상 클래스
abstract class Animal {
abstract public void action();
}
class Dog extends Animal {
@Override
public void action() {
makeSound();
}
private void makeSound() {
System.out.println("Woof, woof!");
}
}
class Cat extends Animal {
@Override
public void action() {
climb();
}
private void climb() {
System.out.println("Climbing a tree");
}
}
public class Main {
public static void main(String[] args) {
// 추상화를 통한 업캐스팅
Animal animal = new Dog();
animal.action(); // Output: Woof, woof!
animal = new Cat();
animal.action(); // Output: Climbing a tree
}
}
Dog
, Cat
은 업캐스팅되어 action
메소드로만 사용이 제한되게 되었다.makeSound()
, climb()
은 main 클래스에서 직접 호출되지 않게 됩니다. (객체 타입과 메서드 은닉)이러한 정보 은닉으로 얻는점은 뭘까?
Animal
클래스 생성으로 Dog
나 Cat
에 의존하지 않는다.조금 더 캡슐화 하기 위해 디자인 패턴을 추가하였습니다.
// 동물을 나타내는 추상 클래스
abstract class Animal {
abstract public void action();
}
// 개를 나타내는 클래스 (Animal을 상속)
class Dog extends Animal {
@Override
public void action() {
System.out.println("Woof, woof!");
}
}
// 고양이를 나타내는 클래스 (Animal을 상속)
class Cat extends Animal {
@Override
public void action() {
System.out.println("Climbing a tree");
}
}
// Animal을 생성하는 팩토리 클래스
class AnimalFactory {
public static Animal createDog() {
return new Dog();
}
public static Animal createCat() {
return new Cat();
}
}
public class Main {
public static void main(String[] args) {
// Factory 패턴을 통한 객체 생성
Animal animal = AnimalFactory.createDog();
animal.action(); // Output: Woof, woof!
animal = AnimalFactory.createCat();
animal.action(); // Output: Climbing a tree
}
}
AnimalFactory
클래스를 구현함으로써 Dog
와 Cat
클래스에 대한 구체적인 객체에 대한 정보를 은닉하였습니다.필드 + 메소드 은닉에 대해서 알아보겠습니다.
아래 코드는 Person
클래스 구현으로 나이와 이름 행동을 나타내는 클래스 입니다.
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
System.out.println("나이는 음수일 수 없습니다.");
}
}
// 행동을 나타내는 메소드
public void eat() {
System.out.println(name + "이(가) 식사합니다.");
}
public void sleep() {
System.out.println(name + "이(가) 잠을 잡니다.");
}
public void work() {
System.out.println(name + "이(가) 일합니다.");
}
// 객체의 정보를 출력하는 메소드
public void introduce() {
System.out.println("안녕하세요, 제 이름은 " + name + "이고, 나이는 " + age + "살입니다.");
}
}
public class Main {
public static void main(String[] args) {
// Person 객체 생성
Person person = new Person("John", 30);
// 캡슐화된 메소드를 통한 동작 수행
person.introduce();
person.eat();
person.sleep();
person.work();
}
}
Person
클래스의 메소드들을 의존하게 됩니다.performDailyRoutine
를 public으로 추가하여 메소드들을 은닉 하도록 하겠습니다.public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
System.out.println("나이는 음수일 수 없습니다.");
}
}
// private 메소드로 변경된 행동을 나타내는 메소드들
private void eat() {
System.out.println(name + "이(가) 식사합니다.");
}
private void sleep() {
System.out.println(name + "이(가) 잠을 잡니다.");
}
private void work() {
System.out.println(name + "이(가) 일합니다.");
}
// public 메소드를 통해 private 메소드 실행
public void performDailyRoutine() {
introduce();
eat();
sleep();
work();
}
// 객체의 정보를 출력하는 메소드
private void introduce() {
System.out.println("안녕하세요, 제 이름은 " + name + "이고, 나이는 " + age + "살입니다.");
}
}
public class Main {
public static void main(String[] args) {
// Person 객체 생성
Person person = new Person("John", 30);
// public 메소드를 통해 private 메소드 실행
person.performDailyRoutine();
}
}
// 행동을 나타내는 인터페이스
interface PersonInterface {
void performDailyRoutine();
}
public class Person implements PersonInterface {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
if (age >= 0) {
this.age = age;
} else {
System.out.println("나이는 음수일 수 없습니다.");
}
}
// private 메소드로 변경된 행동을 나타내는 메소드들
private void eat() {
System.out.println(name + "이(가) 식사합니다.");
}
private void sleep() {
System.out.println(name + "이(가) 잠을 잡니다.");
}
private void work() {
System.out.println(name + "이(가) 일합니다.");
}
// 인터페이스를 구현한 메소드
@Override
public void performDailyRoutine() {
introduce();
eat();
sleep();
work();
}
// 객체의 정보를 출력하는 메소드
private void introduce() {
System.out.println("안녕하세요, 제 이름은 " + name + "이고, 나이는 " + age + "살입니다.");
}
}
public class Main {
public static void main(String[] args) {
// 다형성을 통한 객체 생성
PersonInterface person = new Person("John", 30);
// 인터페이스를 통해 메소드 실행
person.performDailyRoutine();
}
}