Development/CS

[스프링 입문을 위한 자바 객체지향의 원리와 이해] 3장. 자바와 객체지향(다형성, 캡슐화)

lovetan 2025. 3. 7. 16:37

다형성: 사용편의성

오버라이딩(OverRiding)과 오버로딩(OverLoading)

오버라이딩:
같은 메서드 이름, 같은 인자 목록으로 상속 관계에 있는 부모 클래스의 메서드를 재정의.
주로 상속받은 메서드를 자식 클래스의 요구에 맞게 변경하기 위해 사용됨.

오버로딩
같은 메서드 이름, 다른 인자 목록으로 다수의 메서드를 중복 정의.
이때, 메서드의 매개변수 타입이나 개수가 달라야 함.

 

다형성과 T메모리

  • Animal 클래스
    • name: String
    • showName(): void
  • Penguin 클래스 (Animal을 상속)
    • habitat: String
    • showName() : void -> Animal의 showName()을 오버라이딩
    • showName(String yourName) : void <- 오버로딩된 메서드
    • showHabitat(): void

 

다형성의 편리함

다형성은 개발자가 프로그램을 작성할 때 사용편의성을 준다.

  • 오버라이딩은 메서드 재정의 다형성을 제공한다.
    • 하위 클래스가 재정의한 메서드를 알아서 호출해 준다.
    • 덕분에 형변환이나 instance of 연산자를 써서 하위 클래스가 무엇인지 신경 쓰지 않아도 된다.
      • 원래 오버라이딩이 없으면 .bark();를 직접 호출할 수 없고, 형변환을 해야만 사용할 수 있음.
      • instanceof 써서 myAnimal이 Dog인지 확인한 후, Dog로 형변환해서 bark()를 호출해야 함.
    • 부모 클래스 타입의 객체 참조 변수에서 자식 클래스가 오버라이딩한 메서드를 자동으로 호출해준다.
  • 오버로딩은 메서드 중복 정의를 통한 다형성을 제공한다. 
    • 함수명 하나를 갖고 인자 목록만 달리하면 되므로 사용하기 굉장히 편리하다.
      • add라는 함수가 있을 경우, 같은 함수로 인자 타입을 다르게 사용할 수 있다.

 


캡슐화: 정보은닉

정보 은닉(information hiding)

  • 접근 제어자
    • private -
    • [default] ~ 
    • protected #
    • public +

 

 

객체 멤버의 접근 제어자

public class ClassA {

    private int pri;
    int def;
    protected int pro;
    public int pub;
    
    void runSomething() {}
    
    static void runStaticThing() {}

}

 

1. 상속을 받지 않았다면 객체 멤버는 객체를 생성한 후 객체 참조 변수를 이용해 접근해야 한다.

2. 정적 멤버는 [클래스명.정적멤버] 형식으로 접근하는 것을 권장한다. 

 

..?

2번 문장 좀 더 자세히 설명

class Example {
    static int staticVar = 10;  // 정적 변수
    int instanceVar = 20;       // 인스턴스 변수
}
  • 정적(static) 멤버(변수, 메서드)는 객체가 아니라 클래스 자체에 속하므로, 클래스명을 통해 접근하는 것이 좋다.
    • 객체를 통해 접근하면, 마치 개별 객체마다 다른 값이 있는 것처럼 보일 수 있음.
// 권장방식: 클래스명.정적멤버
System.out.println(Example.staticVar);  // ✅ 올바른 접근 방식

// 비권장 방식: 객체참조변수명.정적멤버
Example obj = new Example();
System.out.println(obj.staticVar);  // ⚠️ 가능하지만 권장되지 않음

 

 

또 !

  • public 정적 속성인 pubSt의 경우라면 각 위치 별 객체 멤버 메서드에서 접근할 수 있는 방법은 무려 3 가지이다.

  • 정적 멤버에 접근할 때 [클래스명.정적멤버] 형식으로 왜 접근해야 할지 이유가 느껴지는가?
  • ' 일관된 형식 '으로 접근하기 위해서 이다.
    • 정적멤버는 객체 없이도 사용할 수 있는데, 객체를 통해 접근하게 되면 같은 정적 멤버라도 코드 스타일이 일관되지 않을 것임.
  • ' 불필요한 객체 생성을 방지 '하기 위해서 이다.
    • 정적 멤버를 사용하려고 객체를 만들 필요가 없음.
    • 그런데 객체를 통해 접근하면, 객체를 만들지 않아도 되는 상황에서 객체를 만들게 될 수도 있음.

 


참조 변수의 복사

Call By Value (값에 의한 호출)에 의해 그 값이 복사되며 두 개의 변수는 서로에게 영향을 주지 않는다.

public class CallByValue {
 public static void main(String[] args) {
 int a = 10;
 int b = a;

 b = 20;

 System.out.println(a); // 10
 System.out.printin(b); // 20
 }
}
  • a가 가진 값이 단순히 b에 복사되었다.
  • b에 새로운 값이 입혀져도 a의 값은 변하지 않는다.
  • a와 b 변수는 아무런 관계도 없는 것을 알 수 있다.

  • 기본 자료형 변수는 값을 값 자체로 판단한다.
  • 참조 자료형 변수는 값을 주소 즉 포인터로 판단한다.
  • 기본 자료형 변수를 복사할 때, 참조 자료형 변수를 복사할 때 일어나는 일은 같다. 즉, 가지고 있는 값을 그대로 복사해서 넘겨 준다.