티스토리 뷰

  1. 상속

    • 상속의 정의와 장점
      • 상속이란 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것이다.
      • 적은 양의 코드로 새로운 클래스를 작성할 수 있고, 코드를 공통적으로 관리할 수 있어 관리 및 추가 , 변경에 용이하다.
      • 코드의 재사용성을 높이고, 중복을 제거한다. 프로그램의 생산성과 유지보수에 크기 기여
      • 작성 방법 : 새로 작성할 클래스 이름 extends 상속받고자하는 클래스이름
      • 상속해주는 클래스 : 조상 클래스(상위, 기반(base))
      • 상속받는 클래스 : 자손 클래스(하위, 파생)
      • 화살표는 자손이 부모를 향산다 (상복받았기 때문)
      • 자손 클래스는 부모 클래스의 모든 맴버를 상속받기 때문에 자손 클래스가 더 큰 포함관계를 갖는다고 볼 수 있다.
      • 조상 클래스가 변경되면 자손 클래스는 자동적으로 영향 받지만, 자손 클래스가 변경되는 것은 조상 클래스에 영향을 주지 못한다.
      • 주의
        1. 단, 생성자와 초기화 블럭은 상속되지 않는다. 맴버만 상속된다.
        2. 자손 클래스의 맴버 개수는 조상 클래스보다 항상 같거나 많다.
          • 접근 제어자가 private 또는 default인 맴버들은 상속되지 않기보다는 상속은 받지만 자손 클래스로부터 접근이 제한된다.
      • 클래스 간의 관계에서 형제관계는 없다. 부모 자식 관계만 있다. child1, child2가 같은 parent를 상속받는다해도 둘은 아무런 관계나 영향이 없다.
      • 조상 클래스의 인스턴스 하나를 생성하면, 조상 클래스의 맴버와 자손 클래스의 맴버가 합쳐진 하나의 인스턴스가 된다.
  2. 포함관계

    • 포함관계란 클래스 안에 클래스의 인스턴스를 가지고 있을 때 이다.
    • 가령 circle이 있고, 이안에 point라는 점이 있다면, 이는 포함관계에 있는 것이다.
    • 즉 circle의 맴버 변수로 point라는 클래스가 있는 것이다.
    • 그런데 클래스를 상속하는 것과 포함 관계는 어떻게 구분할까??
    • is-a : a는 b이다. 는 상속관계를 말한다. 즉, 원은 점이다 (불가 원은 원점과 반지름을 가지고 있다.)
    • has-a : a는 b를 가지고 있다.는 포함관계를 말한다. 즉, 원은 점을 가지고 있다. (가능)
    • 따라서 has-a이므로 포함관계를 맺는 것이 맞다.
    • 만약, 원은 도형이다. 라면 원은 도형을 상속받는다.
  3. 단일 상속

    • c++은 다중 상속을 지원하지만, java는 단일 상속을 지원한다.
    • 이는 두 조상에게서 상속을 받을 때, 만약 맴버함수 이름으로 power()가 있다고 하면 어떻게 할까?
    • 이는 구별할 방법이 없기 때문에 문제가 생긴다.
  4. Object 클래스 - 모든 클래스의 조상

    • Object는 모든 클래스 상속 최상위에 있는 조상 클래스이다.
    • 자동적으로 Object클래스로부터 상속받게 함으로서 이것이 가능하다.
    • toString(), equals()를 모든 클래스가 사용할 수 있는 가장 큰 이유가 바로 Object때문이다.
  5. 오버라이딩

    • 조상 클래스로 부터 상속받은 메서드의 내용을 변경하는 것을 오버라이딩이라고 한다.

    • 오버라이딩의 조건

      1. 이름이 같아야 한다.
      2. 매개변수가 같아야 한다.
      3. 반환 타입이 같아야 한다.
    • 즉 오버로딩과 헷갈리지 말자

    • 정리하자면 선언부가 서로 일치해야한다는 것이며, 접근 제어자나 예외는 제한된 조건 하에서만 다르게 변경할 수 있다.

      1. 접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
        넓은 순서 : public, protected, (default) , private 이다. 이에 따라 부모가 protected라면 private나 , default는 불가능하다. public과 protected만 가능하다.
      1. 조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 없다.

        class Parent{
           void parentMethod() throws IOException, SQLException{
           }     
        }
        class Child extends Parent{
           void parentMethod() throws IOException{
           } 
        }

        위와 같이 선언된 예외의 범위가 벗어나면 안된다. 그러나 만약 throws Exception으로 선언한다면
        이는 문제가 된다. 범위가 Exception이 더 큰 조상이기 때문이다. 따라서 개수문제가 아니라 범위 문제가 더 크다.

        • 조상 클래스의 메서드를 자손 클래스에서 오버라이딩 할 때
          1. 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
          2. 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다.
          3. 인스턴스 메서드를 static메서드로 또는 그 반대로 변경할 수 없다. (static은 오버라이드 되지 않는다.)
    • 오버로딩 vs 오버라이딩

      1. 오버로딩은 기존에 없는 새로운 메서드를 추가하는 것이다.
      2. 오버라이딩은 조상으로부터 상속받은 메서드의 내용을 변경하는 것이다.
    • super

      • 자손 클래스로가 조상 클래스로부터 상속받은 맴버를 참조하는데 사용되는 참조변수이다.

      • 사실 super와 this는 근본적으로 같다. 즉, 참조하는 메모리 주소가 같다.

      • 그러나, 상속 맴버와 자신의 맴버를 구분하기 위해 사용하는 것이 좋다.

        class Parent{
          int x = 10;
        }
        class Child extends Parent{
          int x = 20;
          System.out.println(super.x); // 10
          System.out.println(this.x); // 20
        }
      • 이렇게 상속하는 맴버 변수와 상속받는 맴버 변수가 이름이 같을 때 super와 this의 값이 차이가 난다.
        맴버 변수뿐만 아니라, 메서드도 호출할 수 있다.

      • 가령 조상 클래스의 메서드를 자손 클래스에서 오버라이딩한 경우에 super를 사용한다.
        이를 이용하여 조상 메서드를 호출 가능하다.

          class Point{
              int x, y;
              String getLocation(){
                  return "x + y "+ x+ y;
              }
          }
        
          class Point3D extends Point{
              int z;
              String getLocation(){
                  return super.getLocation() + z;
              }
          }

        조상클래스의 메서드의 내용에 추가적으로 작업을 덧붙이는 경우라면, 이처럼 super를 사용해서 조상클래스의 메서드를 포함시키는 것이 좋다.
        후에 조상클래스의 메서드가 변겨오디더라도 변경된 내용이 자손 클래스의 메서드에 자동적으로 반영될 것이기 때문이다.

    • super() - 조상 클래스의 생성자

      • this()와 마찬가지로, super() 역시도 생성자이다.

      • this()는 같은 클래스의 다른 생성자를 호출하는 데 사용되지만, super()는 조상 클래스의 생성자를 호출하는데 사용된다.

      • 자손 클래스의 인스턴스를 생성하면, 자손의 맴버와 조상의 맴버가 모두 합쳐진 하나의 인스턴스가 생성된다.

      • 이 때 조상 클래스 맴버의 초기화 작업이 수행되어야 하기 때문에 자손 클래스의 생성자에서 조상 클래스의 생성자를 호출되어야 한다.

      • 그래서 Object 클래스를 제외한 모든 클래스의 생성자는 첫 줄에 반드시 자신의 다른 생성자 또는 조상의 생성자를 호출해야 한다.

      • 그렇지 않으면 컴파일러는 생성자의 첫 줄에 super();을 자동으로 추가할 것이다.

      • 만약 생성자에 super()을 안써주면, 컴파일러가 super(); 를 모든 자손 생성자의 첫줄에 추가해준다.

      • 그런데, 만약 조상의 생성자 중에 super()로 호출될 수 있는 생성자가 없다면 에러가 생긴다.

        class Point{
          int x , y;
          Point(int x, int y){
        
          }
        }
        
        class Point3D extends Point{
          int z;
          Point3D(int x, int y, int x){
              // super(); 을 자동으로 넣어주는데, Point 클래스에서 생성자가 없어서 에러가 생긴다.
              this.x = x;
              this.y = y;
              this.z = z;
          }
        }
      • 결국 super()가 계속 올라가면 Object()의 생성자가 실행된다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
TAG
more
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함