[TIL] 코드스테이츠 SEB BE Day 12

💡 Today I Will Learn

  • 상속
  • 캡슐화

✏️ Summary


  • 상속

    OOP 핵심 중 하나로 기존의 클래스를 재사용하여 새 클래스를 작성하는 방법이다.
    상위 클래스의 멤버들을 하위 클래스에서 사용할 수 있게 하는 관계를 상속이라한다.
    즉, 하위 클래스에서 정의하는 멤버들까지 포함하면 상위 클래스의 멤버 개수보다 하위 클래스의 멤버 개수가 많다.
    상속관계는 extends 키워드를 사용하므로 ‘확장되었다’ 라고도 표현된다.

    상속_다이어그램

    하위 클래스에서 공통적으로 사용되는 속성과 기능은 상위 클래스에 정의되어있다.
    즉, 상속을 이용하면 코드를 재사용할 수 있어 코드의 중복을 제거할 수 있는 이점이 있다.
    더 나아가, ‘가수는 사람이다’라는 다형적 표현이 가능하다.

    public class Person {
      String name;
      int age;
    
      public void learn(){};
      public void walk(){};
      public void eat(){};
    }
    
    class Programmer extends Person{
      private String companyName;
    
      public void coding(){};
    }
    
    class Singer extends Person {
      private String bandName;
    
      public void singing(){};
    }
    

    클래스 상속은 extends 상위클래스 키워드를 사용하여 정의한다.
    끝으로 자바에서는 단일 상속만 허용한다. 하지만 인터페이스를 통해 다중 상속과 유사하게 구현할 수 있다.

    • 포함관계(composite)

      상속과 유사하게 클래스를 재사용할 수 있는 방법.
      클래스의 멤버로 다른 클래스를 선언하는 것이다.

      public class User{
        String alias;
        String phone;
        Address address;
      
        ...
      }
      
      class Address{
        String city, country;
      
        ...
      }
      

      User 클래스에서 사용 될 city, country 변수를 하나의 Address 클래스에 묶어 선언하여 코드의 중복을 줄였다. 상속과 포함관계를 사용하는 경우는 다음과 같다.

      • ‘IS-A’ 관계에서는 상속: Singer는 Person이다.
      • ‘HAS-A’ 관계에서는 포함: User는 Address를 갖는다.
    • Method Overriding

      상위 클래스의 메서드를 하위 클래스에서 재정의 하는 것을 의미한다.

      public class Person {
        String name;
        private int age;
      
        public void learn(){};
      }
      
      class Programmer extends Person{
          private String companyName;
      
          @Override
          public void learn() {
              System.out.println("프로그래밍을 배운다.");
          }
      }
      

      Programmer 클래스가 learn() 메서드를 오버라이딩하여 적절한 기능으로 수정하였다.
      Method Overriding의 세가지 조건이 있다.

      1. 메서드의 선언부(이름, 매개변수, 반환타입)가 상위 클래스의 메서드와 일치해야 한다.
      2. 접근 제어자의 범위가 상위 클래스의 메서드보다 같거나, 넓어야 한다.
      3. Exception은 상위 클래스의 메서드보다 많이 선언할 수 없다.
      Person[] people = new Person[]{new Programmer(), new Singer()};
      
            for (Person person : people) {
                person.learn();
            }
      

      상위 클래스 객체에 하위 클래스의 인스턴스들을 생성하여 다형적 표현이 가능하다.
      또한 하위 클래스에서 재정의한 메서드들이 수행된다.

    • super와 super()

      this, this()와 유사하게 super는 상위 클래스의 객체, super()는 상위 클래스의 생성자를 의미한다.

      class Super{
        int v1;
        int v2;
      
        public void method(){
      
        }
      }
      
      class This extends Super{
          int v1;
      
          public void method(){
              System.out.println(super.v1);
              System.out.println(v2);
          }
      }
      

      This의 인스턴스 변수명과 상위클래스(Super)의 인스턴스 변수명이 같으므로 super키워드로 구분지어준다.

      class Super{
      
        public Super(){
          super();
          System.out.println("super");
        }
      }
      
      class This extends Super{
      
          public This(){
            super();
          }
      }
      

      모든 생성자의 첫줄에는 반드시 this() 또는 super()가 선언되어야 한다.
      super()가 없는 경우 컴파일러가 첫 줄에 자동으로 super()를 삽입한다.
      이때, 상위 클래스에 default 생성자가 없다면? 에러가 발생한다.

  • Object 클래스

    클래스 상속의 계층 최상위에 위치한 클래스이다.
    즉, 자바의 모든 클래스는 Object클래스를 상속받는다.
    extends 키워드로 명시하지 않아도 컴파일러가 자동으로 추가한다.

    메서드내용
    String toString()객체 정보를 문자열로 출력
    boolean equals(Object obj)== 연산으로 스택 메모리값 비교
    int hashCode()객체의 위치정보 관련. Hashtable 또는 HashMap에서 동일 객체여부 판단
    void wait()현재 쓰레드 일시정지
    void notify()일시정지된 쓰레드 재실행
  • 캡슐화

    또한 OOP 핵심 중 하나인 캡슐화는 객체 내 속성과 기능을 캡슐로 싸서 데이터를 외부로부터 보호하는 것을 뜻한다.

    1. 데이터 보호
    2. 불필요한 외부노출 방지

    캡슐화의 큰 장점은 정보 은닉(Data Hiding)에 있다. 외부로부터의 변경을 막고, 다른 객체에 영향을 주지 않게 독립성을 확보한다.

    • 패키지

      목적이 같은 클래스와 인터페이스의 묶음.
      패키지는 클래스를 그룹화하여 관리가 효율적이다. 윈도우의 디렉터리와 비슷한 역할을 한다고 생각하면 된다.
      패키지는 물리적인 디렉토리라 생각할 수 있으며, 계층간 (.)으로 구분된다.

      package practice.test;
      
      public class Test{
      
      };
      

      패키지에 속한 경우 package로 표시해주어야 한다.

      • 대표적인 예
        1. java.lang: 기본 클래스
        2. java.util: 확장 클래스
        3. java.io / java.nio: 입출력

      같은 이름의 클래스라도 다른 패키에 존재한다면 사용가능하다. 큰 규모의 프로젝트에서는 중복을 방지하는 효과적인 방법이다.

      • (번외) unnamed package
        모든 클래스는 하나 이상의 패키지에 포함되어야 한다.
        만약 패키지가 하나도 선언되어 있지 않다면 컴파일러가 Default로 이름없는 패키지(unnamed package)에 포함해 컴파일한다.
        즉 패키지를 명시하지 않은 모든 클래스와 인터페이스는 같은 패키지에 들어가는 것이다.
    • import

      다른 패키지에 존재하는 클래스를 사용하기 위해 정의해야하는 키워드이다.

        package practice.test;
      
        public class Test{
      
        };
      
        // import 키워드 사용 X
        package practice.test2;
      
        public class practice{
          practice.test.Test test = new practice.test.Test();
        }
      
        // import 키워드 사용 시
        package practice.test2;
        import practice.test.*;
      
        public class practice{
          Test test = new Test();
        }
      
    • 접근 제어자(Access Modifier)
      • 제어자(Modifier)

        클래스, 필드, 메서드, 생성자 등에 의미를 부여하는 키워드이다.

        접근 제어자public, protected, default, private
        기타 제어자static, final, abstract, native, transient, synchronized 등.

        형용사로 수식한다는 느낌으로 사용하며, 접근 제어자는 대상에 하나만 사용할 수 있다.

      • 접근 제어자

        접근 제어자동일 클래스동일 패키지다른패키지
        상속받은 클래스
        다른 패키지
        privateOXXX
        defaultOOXX
        protectedOOOX
        publicOOOO
      • 기타 제어자

        1. final
          상수(constant)를 만든다.
          클래스에 지정한다면 타 클래스에서 상속받을 수 없다.
          메서드에 지정한다면 오버라이딩하여 재정의할 수 없다.

        2. static
          ‘공통적인’ 이라는 공유의 의미를 갖는다.
          변수에 사용하면 클래스 변수(static variable)
          메서드에 사용하면 클래스 메서드(static method)
          초기화 blcok에도 사용할 수 있다.

          • 프로그램 시작 시 최초에 한번 생성 및 초기화된다.
          • 인스턴스 생성없이 사용 가능
          • 해당 클래스의 모든 인스턴스가 공유
        3. abstract
          ‘추상적인’ 이라는 의미로 구현부가 없는 메서드를 추상 메서드라하며, 하나 이상의 추상메서드를 포함하는 클래스도 추상 클래스라한다.

        • 불가능한 조합
        대상조합
        클래스public, (default), final, abstract
        메서드접근제어자, final, static, abstract
        필드접근제어자, final, static
        지역변수final
        초기화블록static
        1. abstract final Class: 상속X
        2. abstract static Method: 구현되지않은 메서드 사용.
        3. private abstract Method: 하위클래스에 접근하지못해 재정의 불가.
        4. private final Method: 함께 사용할 필요가 없다. (두 제어자 모두 재정의 불가능의 의미)
    • getter와 setter 메서드

      캡슐화된 경우 멤버변수의 변경이 필요할때 사용된다.

      class Test{
        private int v1;
        private int v2;
      
        public String getV1(){// getter
          return v1;
        }
      
        public String getV1(){// getter
          return v2;
        }
      
        public int setV1(int v1){// setter
          this.v1=v1;
        }
      
        public int setV2(int v2){// setter
          this.v2=v2;
        }
      }
      

      getter, setter 메서드를 활용하여 캡슐화로 데이터를 보호하면서도 변경할 수 있다.

📌 정리


얼추 알고있던 개념이지만, 확실히 정립되지는 않았던 OOP 핵심 개념이었다. 상속, 캡슐화, 추상화, 다형성은 이번 기회에 확실히 정리해서 머릿속에 각인시켜 놓아야겠다💪

👿 Problem

생성자의 첫줄에는 this(), super()가 반드시 들어간다?

👼 Solution

하위 클래스가 상위 클래스의 멤버를 사용할 수 있으므로, 상위 클래스를 우선적으로 추가하는 super() 메서드가 첫 줄에 수행된다. 하위 클래스부터 상위 클래스 더 나아가 최상위 클래스인 Object 클래스까지 올라가 마무리된다.
즉, Object 클래스를 제외한 모든 클래스에 생성자 첫줄에는 this() 또는 super()를 호출해 주어야한다.

🎯 Tomorrow


  • 다형성
  • 추상화

Back to [TIL] 코드스테이츠 SEB BE Day 11