[Chapter 7] 객체지향 프로그래밍 2_3

slchoi·2022년 1월 13일
0

자바의 정석

목록 보기
16/19
post-thumbnail

'자바의 정석 3rd Edition'을 공부하며 정리한 내용입니다.

6. 추상클래스(abstract class)


6.1 추상클래스란?

  • 추상클래스는 미완성 설계도
  • 클래스가 미완성이라는 것은 멤버의 개수에 관계된 것이 아니라, 단지 미완성 메서드(추상 메서드)를 포함하고 있다는 의미
  • 추상클래스로는 인스턴스를 생성할 수 없으며, 추상클래스는 상속을 통해 자손클래스에 의해서만 완성될 수 있음
  • 추상클래스는 새로운 클래스를 작성하는데 있어 바탕이 되는 조상클래스로서 중요한 의미를 가짐
abstract class 클래스이름 {
	...
}
  • 추상클래스는 키워드 abstract를 붙이면 됨
    • 이 클래스를 사용할 때, 클래스 선언부의 abstract를 보고 이 클래스에는 추상메서드가 있으니 상속을 통해 구현해주어야 한다는 것을 쉽게 알 수 있음
  • 추상클래스는 추상메서드를 포함하고 있다는 것을 제외하고는 일반 클래스와 전혀 다르지 않음
    • 추상클래스에도 생성자가 있으며, 멤버변수와 메서드를 가질 수 있음

6.2 추상메서드(abstract method)

  • 추상메서드: 선언부만 작성하고 구현부는 작성하지 않은 채로 남겨 둔 것
  • 추상메서드 사용 이유
    • 메서드의 내용이 상속받는 클래스에 따라 달라질 수 있기 때문에 조상 클래서에서는 선언부만 작성하고, 주석을 덧붙여 어떤 기능을 수행할 목적으로 작성되었는지 알려 주고, 실제 내용은 상속받는 클래스에서 구현하도록 비워 두는 것
    • 추상클래스를 상속받는 자손 클래스는 조상의 추상 메서드를 상황에 맞게 적절히 구현해주어야 함
/*주석을 통해 어떤 기능을 수행할 목적으로 작성하였는지 설명*/
abstract 리턴타입 메서드이름();
  • abstract를 앞에 붙여주고, {} 대신 문장의 끝을 알리는 ';'을 적어줌
  • 추상클래스로부터 상속받는 자손클래스는 오버라이딩을 통해 조상인 추상클래스의 추상 메서드를 모두 구현해주어야 함
    • 만일 조상으로부터 상속받은 추상메서드 중 하나라도 구현하지 않는다면, 자손클래스 역시 추상클래스로 지정해 주어야 함

6.3 추상클래스의 작성

  • 여러 클래스에 공통적으로 사용될 수 있는 클래스를 바로 작성하기도 하고, 기존의 클래스의 공통적인 부분을 뽑아서 추상클래스로 만들어 상속하는 경우도 있음
  • 상속이 자손 클래스를 만드는데 조상 클래스를 사용하는 것이라면, 반대로 추상화는 기존의 클래스의 공통부분을 뽑아내서 조상 클래스를 만드는 것
    • 상속계층도를 따라 내려올수록 클래스는 점점 기능이 추가되어 구체화의 정도가 심해지며, 상속계층도를 따라 올라갈수록 클래스는 추상화의 정도가 심해진다고 할 수 있음
    • 상속계층도를 따라 내려 갈수록 세분화되며, 올라갈수록 공통요소만 남게 됨

추상화 클래스간의 공통점을 찾아내서 공통의 조상을 만드는 작업
구체화 상속을 통해 클래스를 구현, 확장하는 작업

추상메서드로 하는 대신 아무 내용이 없는 일반 메서드({})로 작성할 수 있는데 추상메서드로 선언하는 이유

  • 자손 클래스에서 추상메서드를 반드시 구현하도록 강요하기 위해서
  • 추상메서드로 정의되어 있지 않고 빈 몸통만 가지도록 정의되어 있다면, 상속받는 자손 클래스에서는 이 메서드들이 온전히 구현된 것으로 인식하고 오버라이딩을 통해 자신의 클래스에 맞도록 구현하지 않을 수 있음
  • abstract를 사용해 추상메서드로 정의해놓으면, 자손 클래스를 작성할 때 내용을 구현해주어야 한다는 사실을 인식하고 자신의 클래스에 알맞게 구현할 것

7. 인터페이스(interface)


7.1 인터페이스란?

  • 인터페이스: 추상클래스처럼 추상메서드를 갖지만 추상클래스보다 추상화 정도가 높아서 추상클래스와 달리 몸통을 갖춘 일반 메서드 또는 멤버변수를 구성원으로 가질 수 없음
    • 오직 추상메서드와 상수만을 멤버로 가질 수 있으며, 그 외의 다른 어떠한 요소도 허용하지 않음
  • 추상클래스를 부분적으로만 완성된 '미완성 설계도'라고 한다면, 인터페이스는 구현된 것은 아무 것도 없고 밑그림만 그려져 있는 '기본 설계도'라고 할 수 있음

7.2 인터페이스의 작성

interface 인터페이스이름 {
	public static final 타입 상수이름 =;
	public abstract 메서드이름(매개변수목록);
}
  • interface에는 접근제어자로 public 또는 default만 사용 가능

인터페이스 멤버 제약 사항

  • 모든 멤버변수는 public static final이어야 하며, 생략 가능
  • 모든 메서드는 public abstract이어야 하며, 생략 가능. 단, static 메서드와 디폴트 메서드는 예외(jdk 1.8부터)
  • 원래는 인터페이스의 모든 메서드는 추상메서드이어야 하는데, JDK 1.8부터 인터페이스에 static 메서드와 디폴트 메서드의 추가를 허용하는 방향으로 변경됨

7.3 인터페이스의 상속

  • 인터페이스는 인터페이스로부터만 상속받을 수 있으며, 클래스와 달리 다중상속이 가능
  • 자손 인터페이스는 조상 인터페이스에 정의된 멤버를 모두 상속 받음

7.4 인터페이스의 구현

class 클래스이름 implements 인터페이스이름 {
	// 인터페이스에 정의된 추상 메서드를 구현해야 함
}
  • 인터페이스는 그 자체로는 인스턴스를 생성할 수 없음
  • 인터페이스에 정의된 추상메서드의 몸통을 만들어주는 클래스를 작성해야 하는데, 방법은 추상클래스가 자신을 상속받는 클래스를 정의하는 것과 같음
    • 인터페이스는 구현한다는 의미의 키워드 implements를 사용
  • 인터페이스의 메서드 중 일부만 구현한다면, abstract를 붙여 추상클래스로 선언해야 함
  class 클래스이름 extends 상속받을인터페이스이름 implements 구현할인터페이스이름{
  	...
  }
  • 상속과 구현을 동시에 할 수 있음

7.6 인터페이스를 이용한 다형성

  • 해당 인터페이스 타입의 참조변수로 인터페이스를 구현한 클래스의 인스턴스를 참조할 수 있으며, 인터페이스 타입으로의 형변환도 가능
Fightable f = (Fightable)new Fight();

or

Fightable f = new Fighter();
  • 인터페이스 Fightable을 클래스 Fighter가 구현했을 때, Fighter 인스턴스를 Fightable타입의 참조변수로 참조하는 것이 가능
  • Fightable 타입의 참조변수로는 인터페이스 Fightable에 정의된 멤버들만 호출이 가능
  • 인터페이스는 메서드의 매개변수의 타입으로 사용 가능
    • 인터페이스 타입의 매개변수가 갖는 의미: 메서드 호출 시 해당 인터페이스를 구현한 클래스의 인스턴스를 매개변수로 제공해야한다는 것
  • 메서드의 리턴타입으로 인터페이스의 타입을 지정해주는 것도 가능
    • 리턴타입이 인터페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미

7.7 인터페이스의 장점

  • 개발시간 단축
  • 표준화 가능
  • 서로 관계없는 클래스들에게 관계를 맺어 줄 수 있음
  • 독립적인 프로그래밍이 가능

1. 개발시간 단축

  • 인터페이스가 작성되면, 이를 사용해 프로그램을 작성하는 것이 가능
    • 메서드를 호출하는 쪽에서는 메서드의 내용에 관계없이 선언부만 알면 되기 때문
  • 동시에 한 쪽에서는 인터페이스를 구현하는 클래스를 작성하게 하면, 인터페이스를 구현하는 클래스가 작성될 때까지 기다리지 않고도 양쪽에서 동시에 개발을 진행할 수 있음

2. 표준화 가능

  • 프로젝트의 기본 틀을 인터페이스로 작성한 후, 개발자들에게 인터페이스를 구현하여 프로그램을 작성하도록 함으로써 일관되고 정형화된 프로그램의 개발이 가능

3. 서로 관계없는 클래스들에게 관계를 맺어 줄 수 있음

  • 상속관계에 있지도 않고, 같은 조상 클래스를 가지고 있지 않은 서로 아무런 관계도 없는 클래스들에게 하나의 인터페이스를 공통적으로 구현하도록 함으로써 관계를 맺어 줄 수 있음

4. 독립적인 프로그래밍이 가능

  • 인터페이스를 이용하면 클래스의 선언과 구현을 분리시킬 수 있기 때문에 실제구현에 독립적인 프로그램을 작성하는 것이 가능
  • 클래스와 클래스간의 직접적인 관계를 인터페이스를 이용해 간접적으로 변경하면, 한 클래스의 변경이 관련된 다른 클래스에 영향을 미치지 않는 독립적인 프로그래밍이 가능

7.8 인터페이스의 이해

  • 클래스를 사용하는 쪽(User)과 클래스를 제공하는 쪽(Provider)이 있음
  • 메서드를 사용(호출)하는 쪽(User)에서는 사용하려는 메서드(Provider)의 선언부만 알면 됨 (내용은 몰라도 됨)

7.9 디폴트 메서드와 static 메서드

  • 인터페이스의 static 메서드는 접근 제어자가 항상 public이며, 생략 가능함

default 메서드

  • 인터페이스에 메서드를 추가한다는 것은, 추상 메서드를 추가한다는 것이고, 이 인터페이스를 구현한 기존의 모든 클래스들이 새로 추가된 메서드를 구현해야 함
  • 디폴트 메서드는 추상 메서드의 기본적인 구현을 제곻나는 메서드
    • 추상 메서드가 아니기 때문에 디폴트 메서드가 새로 추가되어도 해당 인터페이스를 구현한 클래스를 변경하지 않아도 됨
  • 디폴트 메서드는 앞에 키워드 default를 붙이며, 추상 메서드와 달리 일반 메서드처럼 몸통 {}이 있어야 함
  • 디폴트 메서드는 접근 제어자가 public이며, 생략 가능함
  • 새로 추가된 디폴트 메서드가 기존의 메서드와 이름이 중복되어 충돌하는 경우가 발생하는데, 충돌을 해결하는 규칙은 아래와 같음

    1. 여러 인터페이스의 디폴트 메서드 간의 충돌

    • 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩해야 함

    2. 디폴트 메서드와 조상 클래스의 메서드 간의 충돌

    • 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시됨

8. 내부 클리스(inner class)


8.1 내부 클래스람?

  • 클래스 내에 선언된 클래스
  • 클래스에 다른 클래스를 선언하는 이유는 두 클래스가 서로 긴밀한 관계에 있기 때문

내부 클래스 장점

  • 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있음
  • 코드의 복잡성을 줄일 수 있음 (캡슐화)

8.2 내부 클래스의 종류와 특징

내부 클래스특징
인스턴스 클래스(instance class)외부 클래스의 멤버변수 선언위치에 선언. 외부 클래스의 인스턴스멤버처럼 다뤄짐. 주로 외부 클래스의 인스턴스멤버들과 관련된 작업에 사용될 목적으로 선언됨
스태틱 클래스(static class)외부 클래스의 멤버변수 선언위치에 선언. 외부 클래스의 static 멤버처럼 다뤄짐. 주로 외부 클래스의 static 멤버, 특히 ststic 메서드에서 사용될 목적으로 선언됨
지역 클래스(local class)외부 클래스의 메서드나 초기화블럭 안에 선언. 선언된 영역 내부에서만 사용 가능
익명 클래스(anonymous class)클래스의 선언과 객체의 생성을 동시에 하는 이름없는 클래스 (일회용)

8.4 내부 클래스의 제어자와 접근성

  • 인스턴스클래스와 스태틱 클래스는 외부 클래스의 멤버변수와 같은 위치에 선언되며, 멤버변수와 같은 성질을 가짐
  • 내부 클래스가 외부 클래스의 멤버와 같이 간주되고, 인스턴스 멤버와 static 멤버 간의 규칙이 내부 클래스에도 똑같이 적용됨
  • 내부 클래스도 클래스기 때문에 abstract나 final 같은 제어자를 사용할 수 있고, 멤버변수들처럼 private, protected와 접근제어자도 사용 가능
  • 내부 클래스 중 스태틱 클래스만 static 멤버를 가질 수 있음
    • final과 static이 동시에 붙는 변수는 상수이므로 모든 내부 클래스에서 정의 가능
  • 인스턴스 클래스는 외부 클래스의 인스턴스멤버를 객체생성 없이 바로 사용 가능하지만, 스태틱 클래스는 외부 클래스의 인스턴스멤버를 객체생성 없이 바로 사용 불가
  • 인스턴스 클래스는 스태틱 클래스의 멤버들을 객체생성 없이 사용 가능하지만, 스태틱 클래스에서는 인스턴스 클래스의 멤버들을 객체생성 없이 사용 불가

8.5 익명 클래스(anonymous class)

new 조상클래스이름 () {
	// 멤버 선언
}

or

new 구현인터페이스이름 () {
	// 멤버 선언
}
  • 클래스의 선언과 객체 생성을 동시에 하기 때문에 단 한번만 사용가능하고 하나의 객체만을 생성할 수 있는 일회용 클래스
  • 이름이 없기 때문에 생성자를 가질 수 없으며, 조상클래스의 이름이나 구현하고자 하는 인터페이스의 이름을 사용해서 정의하기 때문에 하나의 클래스로 상속받는 동시에 인터페이스를 구현하거나 둘 이상의 인터페이스를 구현할 수 없음
    • 하나의 클래스를 상속받거나 하나의 인터페이스만 구현 가능

Chapter 7 끝!!!

profile
예비 백엔드 개발자

0개의 댓글