Skip to content

Latest commit

 

History

History
100 lines (88 loc) · 8.54 KB

java-the-oop-part-2.md

File metadata and controls

100 lines (88 loc) · 8.54 KB

Java의 정석 객체지향 프로그래밍 2 내용 정리

상속

  • 상속의 정의와 장점
    • 상속이란, 기존의 클래스를 재사용하여 새로운 클래스를 작성하는 것.
    • 간단히 얘기하면 기존의 클래스를 '확장'하는 것이라고 생각하면 된다. 키워드가 extends 임에서 유추할 수 있다.
    • 보다 적은 양의 코드로 새로운 클래스를 작성할 수 있고, 코드를 공통적으로 관리할 수 있기 때문에 코드의 추가 및 변경이 매우 용이하다.
    • 자바에서는 새로 작성하고자 하는 클래스를 정의할 때, 클래스 이름 뒤에 상속받고자 하는 클래스의 이름을 extends {클래스명}형식으로 작성한다.
    • 두 클래스 간에는 상속 관계가 형성되며, 상속을 해주는 클래스를 조상 클래스, 부모 클래스, 상위 클래스, 기반 클래스라고 하며, 상속을 받는 클래스를 자손 클래스, 자식 클래스, 하위 클래스, 파생된 클래스라고 한다.
    • 자손 클래스는 조상 클래스의 모든 멤버를 상속받는다.
    • 클래스간의 관계에서는 형제 관계 같은 것은 없다.
    • 클래스 간의 상속 관계를 적절히 맺어주는 것이 객체지향 프로그래밍 관점에서 중요하다.

클래스간의 관계 - 포함관계

  • 클래스를 재사용하는 또 다른 방법, 한 클래스의 멤버변수로 다른 클래스 타입의 참조변수를 선언하는 것
  • 단위별로 여러 개의 클래스를 작성한 다음, 포함관계로 재사용 하면 보다 간결하고 손쉽게 클래스를 작성할 수 있다.
  • 작성된 단위 클래스는 다른 클래스를 작성하는데 재사용 가능하다.
  • 단위 클래스 별로 코드가 작게 나뉘어 있다면 코드 관리가 용이해진다.
  • 상속과 포함관계를 결정하는 방법
    • is ~ a, has ~ a 관계 얘기가 나온다.
  • 조상 클래스에 정의된 메서드와 같은 메서드를 자손 클래스에 정의하는 것이 '오버라이딩'

단일 상속

  • C++은 다중 상속을 지원한다. 반면 자바는 단일 상속만을 허용한다.
  • 다중상속의 허용은 클래스 간의 관계를 복잡하게 만들 가능성이 높고, 멤버의 이름이 겹치는 문제가 발생할 수 있다.
    • 따라서 자바는 다중상속의 단점을 포기하는 대신 클래스간의 관계를 명확하게 하고 코드를 신뢰할 수 있도록 만드는 단일상속을 채택했다.
  • Object 클래스는 모든 클래스의 조상 클래스다. 만약 상속하지 않는 클래스라면 컴파일러가 알아서 extends Object를 추가해준다.
    • 따라서 Object에 정의된 멤버를 우리가 사용할 수 있는 것이다.

오버라이딩

  • 오버라이딩은 조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것
  • 오버라이딩을 할 때 메서드의 선언부는 조상의 것과 완전히 일치해야한다.
    • 이름이 같아야 하고, 매개변수와 반환타입 또한 같아야 한다.
    • 접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
    • 더 많은 수의 예외를 선언할 수는 없다.
    • 인스턴스 메서드와 클래스 메서드를 바꿀수는 없다.
      • 클래스 메서드는 오버라이딩 자체가 안된다. (클래스에 묶여있다.)
  • 오버로딩 vs 오버라이딩
    • 하나는 새로운 것을 만드는 것이고 다른 하나는 기존에 존재하던 것을 바꾸는 것이다.
  • super
    • super는 자손 클래스에서 조상 클래스로부터 상속받은 멤버를 참조하는데 사용되는 참조변수이다.
    • 상속된 멤버와 자신의 멤버의 이름이 같을때 구분하는 용도로 사용할 수 있다.
    • superthis는 근본적으로 같다.
    • static 에서는 당연히 사용할 수 없다.
    • 오버라이딩 할 때, 자손의 메서드가 조상의 메서드의 작업에 단순히 작업을 덧붙이는 경우라면 super를 사용해서 조상클래스의 메서드를 포함시키는 것이 좋다. (변경사항이 자동으로 반영된다.)
  • super() - 조상 클래스의 생성자
    • this()와 마찬가지이다. 자손 클래스의 인스턴스를 생성하면 조상 클래스의 멤버도 초기화해야하기 때문에 사용한다.
    • 생성자의 첫 줄에서 사용한다. 자손 클래스의 멤버가 조상 클래스의 멤버를 사용할 수도 있기 때문이다.
    • Object를 제외한 모든 클래스의 생성자는 첫 줄에 반드시 자신의 다른 생성자 또는 조상의 생성자를 호출해야 한다. 없다면 컴파일러가 super()를 자동으로 추가해준다.

packageimport

  • 패키지는 클래스의 묶음이다.
    • 클래스, 인터페이스를 포함시킬 수 있고, 연관된 클래스들을 그룹 단위로 묶어서 효율적으로 관리할 수 있도록 한다.
    • 같은 이름의 클래스더라도 다른 패키지에 존재하는 것이 가능해서 이름 충돌을 막을 수 있다.
    • 클래스의 실제 이름은 패키지명까지 포함한다.
    • 클래스가 물리적으로 하나의 클래스파일인 것과 같이 패키지는 물리적으로 하나의 디렉토리다.
    • 패키지는 하위 패키지를 포함할 수 있다.
    • 패키지를 선언하는 것은 클래스나 인터페이스에서 첫 문장에 선언해준다.
    • 패키지명은 소문자가 관례적으로 사용된다.
    • 패키지의 루트 디렉토리를 클래스패스(classpath)에 포함시켜야 하며, 클래스패스는 컴파일러나 JVM 등이 클래스의 위치를 찾는데 사용되는 경로다.
      • 실행시에 -cp 옵션을 이용해서 일시적으로 클래스패스를 지정해 줄 수도 있다.
  • import
    • 다른 패키지의 클래스를 미리 명시해주어 소스코드에서 패키지명을 생략할 수 있도록 해준다.
    • 클래스 이름을 지정해주는 대신 *를 사용할 수 있는데, 컴파일하는 과정에서만 조금 느려질뿐 실행 시 성능상의 차이는 전혀 없다. 하지만, 명확한 소스코드를 위해 가급적이면 명시적으로 하는 것을 선호하는 편이다.
      • 하위 패키지의 클래스는 포함하지 않는다.
    • import java.lang.* 은 기본적으로 선언되어있다.
    • static import
      • static 멤버를 호출할 때, 클래스 이름을 생략하기 위한 기법
      • 자주 사용하는 경우, 간결한 코드를 위해서 사용

제어자(modifier)

  • 제어자(modifier)는 클래스, 변수 또는 메서드의 선언부에 함께 사용되어 부가적인 의미를 부여한다.
    • 접근 제어자(public, protected, default, private)
    • 그 외의 제어자(static, final, abstract, native, transient, synchronized, volatile, strictfp)
      • 몇몇개는 처음보거나 안써봤다.
    • 제어자는 클래스나 멤버변수와 메서드에 주로 사용되며, 여러가지를 조합해서 사용할 수 있다.
    • 접근 제어자는 하나만 선택해서 사용할 수 있다.
    • 제어자는 보통 접근 제어자를 먼저 사용한다.
  • static: 클래스의, 공통적인
    • 인스턴스에 관계없이 같은 값을 가짐. (모든 인스턴스가 공유함)
    • 인스턴스를 생성하지 않고 사용할 수 있다.
    • 멤버변수, 메서드, 초기화 블럭 이외에는 사용할 수 없다.
    • 인스턴스 멤버를 사용하지 않는 메서드는 static을 붙여서 선언하는 것을 고려한다.
      • 더 편리하고 속도가 빠르다는 장점이 있다.
  • final: 마지막의, 변경될 수 없는
    • 변수에 사용하면 값을 변경할 수 없는 상수가 된다., 메서드에 사용하면 오버라이딩을 할 수 없다. 클래스에 사용하면 상속해줄 수 없다.
    • 클래스, 메서드, 멤버변수, 지역변수에 사용가능하며, 메서드 매개변수에도 사용가능 하다.
    • 인스턴스 변수를 final로 선언해두고 생성자에서 초기화되도록 할 수 있다. (자주 쓰인다.)
  • abstract: 추상의, 미완성의
    • 메서드의 선언부만 작성하고 실제 수행내용은 구현하지 않은 추상 메서드를 선언하는데 사용한다.
    • 클래스에 사용되어 클래스 내에 추상메서드가 존재할 수 있다는 것을 알리는 용도로 사용된다.(추상 메서드가 없어도 추상 클래스 선언은 가능하다.)
    • 클래스, 메서드에 사용가능하다.
    • 추상 클래스는 인스턴스 생성이 불가능하다.
      • 인스턴스를 생성하지 못하게 하는 방법으로도 사용가능하다.