[자바와 객체 지향 그리고 스프링] 3- 캡슐화: 정보 은닉

코린이서현이·2024년 1월 5일
0

😄들어가면서😄

캡슐? 💊 너무 귀여워

🎯 목표

📌 접근 제어자 복습하기

📌 접근 제어자

객체 맴버의 접근 제어자

👉 접근제어자 포스팅

public : 어디에서나
protected : 내부 패키지와 외부 패키지의 자식 클래스의 경우
default : 동일 패키지에서만 접근 가능
private : 내부 클래스에서만 접근할 수 있음

접근 제어자같은 클래스의 멤버같은 패키지의 멤버외부 패키지이면서 자식 클래스의 멤버그 외의 영역
public
protectedX
defaultXX
privateXXX

😎 이정도면 된거아니야?
🤮 절대 이님!! 멤버변수와 스태틱 변수간에 , 정적 메서드와 인스턴스 메서드별로 확신 있어?
🙅‍ 없어요

🔖 UML 표기법에서의 접근 제어자 표시

private : -
default : ~
protected : #
public : +

정적 메서드 : 밑줄 (_)

🥲 객체 멤버의 접근제어자 실습

📍 어떤 변수에 접근해야한다 🟰 메모리에 해당 변수가 올라와있어야한다.
즉, 상속 받은 경우에는 상위 클래스의 인스턴스 변수를 가지고 있기 때문에 객체를 생성하지 않고도 접근할 수 있다.
그러나 따로 상속 받지 않은 경우에는 객체를 생성 후 객체 참조 변수를 통해 접근 해야한다.

📍 인스턴스 멤버에 접근하는 경우 :
해당 클래스를 상속 받은 경우에는 this예약어를 통해서 접근할 수 있다.
상속받지 않은 경우에는 객체 참조 변수를 사용한다.

📍 정적 메서드가 접근할 수 있는 변수란?!
정적 메서드는 객체가 생성되기 전에 스태틱으로 올라간다. ✔️ 따라서 이때에 메모리에 올라가 있는 변수만 사용이 가능하다.
🤔 그러면 정적 메서드가 메모리에 올라가 있을 때 올라가 있는 변수는 어떤 것이 있을까..?
👉 static으로 선언된 클래스 변수이거나, 해당 메서드 내에서 직접 객체를 선언해야한다.

📂 packageOne

package OOP03.encapsulation01.packageOne;

public class ClassA {
  private int pri = 1;
  int def = 1;
  protected int pro = 1;
  public int pub;
  
  
  void runSomeThing(){
    int pri1 = this.pri;
    int def1 = this.def;
    int pro1 = this.pro;
    int pub1 = this.pub;

  }

  static void runStaticThing() {
// 📌 정적 메서드는 정적 변수(클래스 변수)만 접근 가능!!
// 정적 메서드에서 멤버 변수로의 접근은 객체를 생성 후에 객체 참조 변수를 통해 접근
    ClassA classA = new ClassA();

    int pri1 = classA.pri;
    int def1 = classA.def;
    int pro1 = classA.pro;
    int pub1 = classA.pub;
  }

}
package OOP03.encapsulation01.packageOne;

public class ClassAA extends ClassA{
  ClassA classA = new ClassA();
  void runSomeThing(){
//    int pri1 = this.pri;
//    private는 내부 클래스에서만 접근이 가능하다.
    int def1 = this.def;
    int pro1 = this.pro;
    int pub1 = this.pub;
  }

  static void runStaticThing() {
//📌 정적 메서드는 정적 변수(클래스 변수)만 접근 가능!!
  }
}
package OOP03.encapsulation01.packageOne;

public class ClassB {

  ClassA classA = new ClassA();
  void runSomeThing(){
//📌 상속 받지 않아도 동일 패키지로 private로 선언된 변수를 제외하면 모두 접근이 가능하다.
//    int pri1 = classA.pri;
    int def1 = classA.def;
    int pro1 = classA.pro;
    int pub1 = classA.pub;
  }

  static void runStaticThing() {
//📌 정적 메서드는 클래스 변수만 접근 가능!!
  }
}

📂 packageTwo

package OOP03.encapsulation01.packageTwo;

import OOP03.encapsulation01.packageOne.ClassA;
//다른 패키지로 import문이 필요하다.

public class ClassAB extends ClassA {

  void runSomeThing(){
//    int pri1 = this.pri;	private 접근 ❌  
//    private는 내부 클래스에서만 접근이 가능하다.
//    int def1 = this.def;	default 접근 ❌  
//    default는 동일한 패키지에서만 접근할 수 있다.

    int pro1 = this.pro;	//다른 패키지이지만, 상속을 받아서 protect 접근이 가능하다.  
    int pub1 = this.pub;	//public 접근 가능
  }

  static void runStaticThing() {
//📌 정적 메서드는 클래스 변수만 접근 가능!!
//    따라서 메서드 내에서 객체를 생성 후 객체 참조 변수를 이용해 접근
    ClassAB classAB = new ClassAB();

//    상속을 받았지만 default는 사용 ❌ 
//    default는 동일한 패키지에서만 접근할 수 있다.
    int pro1 = classAB.pro; // 상속했기 때문에 protect 접근 가능 ⭕ 
    int pub1 = classAB.pub;
  }
}
package OOP03.encapsulation01.packageTwo;

import OOP03.encapsulation01.packageOne.ClassA;

public class ClassC {
  void runSomeThing(){
//📌 ClassA를 상속받지 않았기 때문에 객체를 생성 후 객체 참조 변수를 이용 접근 가능
    ClassA classA = new ClassA();

//   pri,def,pro ❌ 
    int pub = classA.pub;
//📌  ClassA가 속한 패키지와 다른 패키지이기 때문에, public 변수만 접근이 가능하다.
  }

  static void runStaticThing() {
//📌 정적 메서드는 클래스 변수만 접근이 가능하다.
  }
}

🥲 클래스 멤버의 접근제어자 실습

📍 클래스 변수는 어떻게 사용하는 것이 적절할까?
클래스명.정적멤버 형식으로 접근하는 것이 권장된다.
🤔 클래스 변수의 메모리 위치는? -> 스태틱 메모리에 저장되어 모든 곳에서 공유된다.
🤔 클래스 변수는 인스턴스마다 존재하는 것이 아니라, 클래스에 존재한다.

사람 클래스의 다리 개수 -> 클래스 변수 : 2
홍길동의 다리개수...?
강감찬의 다리개수...? 보다는

클래스의 변수로 저장하는 것이 의미적으로도 적절하다.

📂 packageOne

package OOP03.encapsulation02.packageOne;

public class ClassA {
  private int pri = 1;
  int def = 1;
  protected int pro = 1;
  public int pub;

  static private int priSt = 2;
  static int defSt = 3;
  static protected int proSt = 2;
  static public int pubSt = 2;
  void runSomeThing(){
    int priSt1 = ClassA.priSt;
    int defSt1 = ClassA.defSt;
    int proSt1 = ClassA.proSt;
    int pubSt1 = ClassA.pubSt;

    int priSt2 = priSt;
    int defSt2 = defSt;
    int proSt2 = proSt;
    int pubSt2 = pubSt;
  }

  static void runStaticThing() {
    int priSt1 = ClassA.priSt;
    int defSt1 = ClassA.defSt;
    int proSt1 = ClassA.proSt;
    int pubSt1 = ClassA.pubSt;

    int priSt2 = priSt;
    int defSt2 = defSt;
    int proSt2 = proSt;
    int pubSt2 = pubSt;
  }

}
package OOP03.encapsulation02.packageOne;

public class ClassA {
  private int pri = 1;
  int def = 1;
  protected int pro = 1;
  public int pub;

  static private int priSt = 2;
  static int defSt = 3;
  static protected int proSt = 2;
  static public int pubSt = 2;
  void runSomeThing(){
    int priSt1 = ClassA.priSt;
    int defSt1 = ClassA.defSt;
    int proSt1 = ClassA.proSt;
    int pubSt1 = ClassA.pubSt;

    int priSt2 = priSt;
    int defSt2 = defSt;
    int proSt2 = proSt;
    int pubSt2 = pubSt;
  }

  static void runStaticThing() {
    int priSt1 = ClassA.priSt;
    int defSt1 = ClassA.defSt;
    int proSt1 = ClassA.proSt;
    int pubSt1 = ClassA.pubSt;

    int priSt2 = priSt;
    int defSt2 = defSt;
    int proSt2 = proSt;
    int pubSt2 = pubSt;
  }

}
package OOP03.encapsulation02.packageOne;

public class ClassB {

  ClassA classA = new ClassA();
  void runSomeThing(){
//    int priSt1 = ClassA.priSt;
    int defSt1 = ClassA.defSt;
    int proSt1 = ClassA.proSt;
    int pubSt1 = ClassA.pubSt;

//    상속받지 않았기 때문에 ClassB에는 해당 변수들이 없음...
//    int priSt2 = priSt;
//    int defSt2 = defSt;
//    int proSt2 = proSt;
//    int pubSt2 = pubSt;
  }

  static void runStaticThing() {
//    int priSt1 = ClassA.priSt;
    int defSt1 = ClassA.defSt;
    int proSt1 = ClassA.proSt;
    int pubSt1 = ClassA.pubSt;


// 📌 정적 멤버를 객체 참조 변수를 이용해서도 접근할 수 있지만 이런 방식은 추천되지 않는다.
//    클래스 변수는 클래스명.변수명이 적절하다.
    ClassA classA1 = new ClassA();
//    int priSt2 = classA1.priSt;
    int defSt2 = classA1.defSt;
    int proSt2 = classA1.proSt;
    int pubSt2 = classA1.pubSt;
  }
}

📂 packageTwo

\package OOP03.encapsulation02.packageTwo;

import OOP03.encapsulation02.packageOne.ClassA;

public class ClassAB extends ClassA {

  void runSomeThing(){
//    int priSt1 = ClassA.priSt;
//    int defSt1 = ClassA.defSt;
    int proSt1 = ClassA.proSt;
    int pubSt1 = ClassA.pubSt;

//  ClassAB는 CalssA를 상속받아서 바로 접급할 수 있음.
//    int priSt2 = priSt;
//    int defSt2 = defSt;
    int proSt2 = proSt;
    int pubSt2 = pubSt;
  }

  static void runStaticThing() {
//    int priSt1 = ClassA.priSt;
//    int defSt1 = ClassA.defSt;
    int proSt1 = ClassA.proSt;
    int pubSt1 = ClassA.pubSt;

//    int priSt2 = priSt;
//    int defSt2 = defSt;
    int proSt2 = proSt;
    int pubSt2 = pubSt;
  }
}
package OOP03.encapsulation02.packageTwo;


import OOP03.encapsulation02.packageOne.ClassA;

public class ClassC {
  void runSomeThing(){
//  📌 public으로만 가능
    int pubSt = ClassA.pubSt;


    ClassA classA = new ClassA();
    int pubSt1 = classA.pubSt;
  }

  static void runStaticThing() {
    int pubSt = ClassA.pubSt;

    ClassA classA = new ClassA();
    int pubSt1 = classA.pubSt;
  }
}

➕ 값의 복사

기본 자료형 변수의 복사

👉 단순 값이 복사되며, 서로에게 영향을 주지 않는다.

🖥️ 예제코드

package OOP03.reference;

public class CallByValue {
  // 기본 자료형 변수를 복사하는 경우 : 단순 복사, 관계 없음
  public static void main(String[] args) {
    int a = 10;
    int b = a;

    b = 20;

    System.out.println("a = " + a);
    System.out.println("b = " + b);
  }
}

👉 실행화면

a = 10
b = 20

객체 자료형의 복사

🤔 객체 참조 변수를 복사하는 경우는 무엇이 복사될까..?
👉 T 메모리내의 힙 메모리에 있는 인스턴스의 주소가 복사된다.
따라서, 각기 다른 객체 참조 변수가 동일한 인스턴스를 참조하게 되고, 서로의 값에 영향을 받게 된다.

방어적 복사, Getter

🖥️ 실습 코드

package OOP03.reference;


import OOP03.polymorphism01.Anlimal;

public class CallByReference01 {
  public static void main(String[] args) {
    Anlimal ref_a = new Anlimal();
    Anlimal ref_b = ref_a;

    ref_a.age = 10;
    ref_b.age = 20;

    System.out.println("ref_a = " + ref_a);
    System.out.println("ref_b = " + ref_b);

    System.out.println("ref_a.age = " + ref_a.age);
    System.out.println("ref_b.age = " + ref_b.age);
  }
}

👉 실행화면

ref_a = OOP03.polymorphism01.Anlimal@4c873330
ref_b = OOP03.polymorphism01.Anlimal@4c873330
ref_a.age = 20
ref_b.age = 20
profile
24년도까지 프로젝트 두개를 마치고 25년에는 개발 팀장을 할 수 있는 실력이 되자!

0개의 댓글