정보은닉 그리고 캡슐화
정보은닉
정보는 클래스의 인스턴스 변수를 의미
public class Main1 {
public static void main(String[] args) {
Circle c = new Circle(1.5);
System.out.println(c.getArea());
c.setRad(2.5);
System.out.println(c.getArea());
c.setRad(-4.5);
System.out.println(c.getArea());
}
}
class Circle{
double rad = 0;
final double PI = 3.14;
public Circle(double r){
setRad(r);
}
public void setRad(double r){
if (r < 0){
rad = 0;
return;
}
rad = r;
}
public double getArea() {
return (rad * rad) * PI;
}
}
double rad = 0;
final double PI = 3.14;
생성자 초기화 방법 보다는 인스턴스 변수 선언의 초기화.
인스턴스의 직접적 접근을 허용시, 컴파일 과정중 오류 발생. -> 이런 오류 발생되지 않게 하기 위해서 정보 은닉이 필요
정보 은닉을 위한 private 선언
public class Main2 {
public static void main(String[] args) {
Circle2 c = new Circle2(3.4);
System.out.println("반지름 :" + c.getRad());
System.out.println("넓이 :" + c.getArea());
c.setRad(3.4);
System.out.println("반지름 :" + c.getRad());
System.out.println("넓이 :" + c.getArea());
}
}
class Circle2 {
private double rad = 0;
final double PI = 3.14;
public Circle2(double r){
setRad(r);
}
public void setRad(double r) {
if (rad < 0) {
return;
}
rad = r;
}
public double getRad() {
return rad;
}
public double getArea() {
return (rad * rad) * PI;
}
}
인스턴스 변수 앞에 private 선언을 추가 -> 정보은닉 완료
private double rad = 0;
클래스 내부 접근만 허용
인스턴스 변수를 private으로 선언했으니,
public void setRad(double r) {
if (rad < 0) {
return;
}
rad = r;
}
public double getRad() {
return rad;
}
값을 변경 및 불러오는 메소드가 필요하다.
Setter -> 값 설정 / Getter -> 값을 가져옴
접근 수준 지시자
접근 허용 수준을 결정
네 가지 종류의 접근 수준 지시자
public protected private, default
default는 아무 선언도 하지 않은 상황
접근 지시자 선언을 할 수 있는 상황은 2가지
클래스 정의 인스턴스,
인스턴스 변수와 메소드
클래스 정의 대상 -> public, default
인스턴스 변수와 메소드 대상 -> public, protected, private, default
클래스 정의 대상의 public, default 선언이 갖는 의미
Public 선언 시 위치에 상관 없이 어디서든 해당 클래스의 인스턴스를 생성 할 수 있다.
Default 선언되면, 동일 패키지로 묶인 클래스 내에서만 인스턴스 생성이 가능
package chap9.zoo;
public class Cat {
public void makeCat(){
Duck duck = new Duck();
}
public void makeSound(){
System.out.println("야옹");
}
void makeHappy(){
System.out.println("스마일");
}
}
class Duck{
}
package chap9.animal;
import chap9.zoo.Cat;
public class Dog {
public void makeDog(){
Cat yaong = new Cat();
}
public void makeDuck(){
// Duck duck = new Duck();
}
public void welcon(Cat c){
c.makeSound();
}
}
Duck의 경우 default로 선언 되었기 때문에 Dog 클래스에서 컴파일이 불가능 하다. 그리고 클래스의 public의 선언과 관련하여 두가지 상황을 지켜야 한다
하나의 소스파일에 하나의 클래스만 public
소스파일 이름과 public으로 선언된 클래스의 이름을 일차
인스턴스 맴버 대상 public, protected, private, default 선언
Public과 default의 경우 사실상 동일하게 인스턴스 멤버에 적용이 된다.
인스턴스 멤버의 public, default 선언이 갖는 의미
Public : 어디서든 접근 가능
Default : 동일 패키지 내에서만 접근 가능
접근이 된다면 -> 이 의미는 메소드의 호출이 가능하다는 의미이다.
public class Cat {
public void makeCat(){
Duck duck = new Duck();
}
public void makeSound(){
System.out.println("야옹");
}
void makeHappy(){
System.out.println("스마일");
}
}
makeSound = public (어디서든 선언 가능)
makeHappy = default (동일 패키지로 묶인 클래스 내에서 호출 가능)
인스턴스 멤버의 private 선언
Private -> 동일 클래스에 정의된 메소드 내에서만 접근이 가능하다.
인스턴스 멤버의 protected 선언
Protected 삽입은 default 선언이 허용하는 모든 접근을 허용
Default가 허용하지 않는 한 한 영역에서 접근 허용
Default로 선언되면 접근을 허용하지 않지만, protected 선언시 접근을 허용하는 그 “한 영역”이 어딘지만 알면 protected에 대한 이해 끝
package chap9.alpahbet;
public class AAA {
int num;
}
package chap9.alpahbet;
public class BBB extends AAA{
public void init(int n){
num = n;
}
}
BBB 클래스를 보면, init을 보면, 자신의 멤버로 선언되지 않은 변수 num에 접근. 변수 num이 n으로 상속 되었기 때문. (지금은 문제 없음)
하지만 다른 페키지로 만들시 문제가 발생. 이 문제를 해결 하기 위해서는 num을 protected로 선언 하면 된다.
Protected num으로 선언
Protected 선언된 멤버는 상속관계에 있는 다른 클래스에서 접근이 가능
캡슐화
캡슐화를 정의 하자면, 하나의 목적을 이루기 위해 관련 있는 모든 것을 하나의 캡슐에 담아 두는 것
또는 하나의 목적을 이루기 위해 관련 있는 모든 것을 하나의 클래스에 담아 두는 것. 하지만 무조건 많이 담는다고 해서 캡슐화가 아니다. 상황 및 목적에 따라서 동일한 이름의 클래스에도 담기는 내용이 달라진다. 클래스들을 적절히 캡슐화 시키면 프로그램 간결.
public class Main3 {
public static void main(String[] args) {
ColdPatient patient = new ColdPatient();
patient.takeSinivelCap(new SinivelCap());
patient.takeSneezeCap(new SneezeCap());
patient.takeSnuffleCap(new SnuffleCap());
}
}
class SinivelCap{
void take(){
System.out.println("콧물이 싹 납니다.");
}
}
class SneezeCap{
void take(){
System.out.println("재체기가 납니다");
}
}
class SnuffleCap{
void take(){
System.out.println("코가 뻥 뚫립니다.");
}
}
class ColdPatient{
void takeSinivelCap(SinivelCap cap){
cap.take();
}
void takeSneezeCap(SneezeCap cap){
cap.take();
}
void takeSnuffleCap(SnuffleCap cap){
cap.take();
}
}
위 코드를 간결화 (캡슐화)
public class Main3_1 {
public static void main(String[] args) {
ColdPatient1 patient = new ColdPatient1();
patient.takeSinus(new SinusCap());
}
}
class SinusCap{
void sniTake(){
System.out.println("콧물이 싹 납니다.");
}
void sneTake(){
System.out.println("재채기가 멎습니다.");
}
void snuTake(){
System.out.println("코가 뻥 뚫립니다.");
}
void take(){
sneTake();
sniTake();
snuTake();
}
}
class ColdPatient1{
void takeSinus(SinusCap cap){
cap.take();
}
}
해당 클래스와 관련 있는 내용을 하나의 클래스에 모드 담는다.
포함 관계 캡슐화
한 클래스가 다른 클래스의 인스턴스를 멤버로 가질 수 O. -> 포함관계
class SinivelCap1{
void take(){
System.out.println("콧물 괜찮");
}
}
class SneezeCap1{
void take(){
System.out.println("재채기 괜찮");
}
}
class SnuffleCap1{
void take(){
System.out.println("코가 괜찮");
}
}
class SinusCap3{
SinivelCap1 cap1 = new SinivelCap1();
SneezeCap1 cap2 = new SneezeCap1();
SnuffleCap1 cap3 = new SnuffleCap1();
void take(){
cap1.take();
cap2.take();
cap3.take();
}
}
class ColdPatient2 {
void takeSinus3(SinusCap3 cap3){
cap3.take();
}
}
public class Main3_2 {
public static void main(String[] args) {
ColdPatient2 patient2 = new ColdPatient2();
patient2.takeSinus3(new SinusCap3());
}
}
class SinusCap3{
SinivelCap1 cap1 = new SinivelCap1();
SneezeCap1 cap2 = new SneezeCap1();
SnuffleCap1 cap3 = new SnuffleCap1();
void take(){
cap1.take();
cap2.take();
cap3.take();
}
}
<문제>
1.
public class Main4 {
public static void main(String[] args) {
Circle3 circle3 = new Circle3(2,2,3);
circle3.showCircleInfo();
}
}
class Point {
int xPoint;
int yPoint;
public Point(int xPoint, int yPoint) {
this.xPoint = xPoint;
this.yPoint = yPoint;
}
public void showPointInfo() {
System.out.println("[" + xPoint + " , " + yPoint + "]");
}
}
class Circle3 {
int r;
Point center;
public Circle3(int x, int y, int r) {
center = new Point(x, y);
r = r;
}
public void showCircleInfo(){
center.showPointInfo();
System.out.println("반지름: " + r);
}
}