카테고리 없음

추상클래스와 인터페이스

nsh95 2024. 1. 6. 23:54

 

01 추상 클래스와 추상 메서드

package section11;

class Animal {
   void cry() {} // 텅 빈 메서드
 }

class Pig extends Animal {
  @Override
  void cry() {
    System.out.println("꿀꿀");
  }
}
…
calss Farm {
   void sound(Animal animal) {
      animal.cry(); // 매개변수 참조 객체의 오버라이딩된 메서드 호출
  }
}

-Animal 클래스의 cry() 메서드가 텅 비어있는것을 확인할 수 있다.

-Animal 객체를 통해서 직접 cry() 메서드를 호출할 일은 없었지만, Animal 클래스를 상속받은 자식 클래스들이 cry() 메서드를 오버라이딩하여 재정의하고, 타입 변환을 통해서 그 메서드를 각각 사용하기 위함이었다.

1 추상 메서드 (abstract method)

-다형성을 위해 메서드의 선언은 통일해야 하지만, 실제로 구현하는 내용은 자식 클래스마다 달라야 할 때,

부모 클래스의 메서드는 비워두고 자식 클래스에서 오버라이딩하여 구현해낼 수 있다.

-선언부만 작성하고 구현부는 작성하지 않고 남겨둔 미완성 메서드를 '추상 메서드'라고 한다.

-추상 메서드를 선언할 때는 abstract 키워드를 함께 표기해야 한다.

[메서드 구현부인 중괄호{} 대 추상 메서드를 선언하는 방법]

▶[접근제한자] abstract 반환 타입 메서드 이름 (매개변수1, 매개변수2,…);

-Animal 클래스의 cry() 메서드를 추상 메서드로 수정하면

 

public class Animal {
   abstract void cry();
}

▶에러 메시지 : The abstract method cry in type Animal can only be defined by an abstact class

▶'abstract 메서드는 반드시 abstract class 안에 정의되어야 한다'

[추상 메서드의 형태를 갖추게 되면 따라야 하는 제약조건]

▷추상 메서드를 1개 이상 선언하면, 그 클래스는 추상 클래스로 선언되어야 한다.

※ 추상(abstract)의 사전적 의미 : 구체성 없이 일반적인 것

2 추상 클래스 (abstract class)

-하나 이상의 추상 메서드를 포함하는 클래스를 가리켜 추상 클래스라고 한다.

-추상 클래스는 추상 메서드를 포함하고 있다는 것을 제외하고는 일반 클래스와 다르지 않다.

-추상 클래스에도 생성자가 있으며, 멤버변수와 메서드도 가질 수 있다.

[추상 클래스를 선언하는 방법]

 

[접근 제한자] abstract class 클래스 이름 {
   // 필드
   // 생성자
   // 메서드 (추상 메서드 포함)
}

[추상 클래스로 선언되는 클래스의 제약 조건]

▷일반 클래스처럼 독립적으로 생성자를 호출해 객체를 생성할 수 없다.

▷자식 클래스의 생성자에서 super()를 통해 추상 클래스의 생성자를 호출하여 부모 객체를 생성한 후 자식 객체를 생성한다.

※추상 클래스가 반드시 추상 메서드를 가져야하는건 아니다.

[추상 메서드가 선언된 추상 클래스의 힘]

▷추상 클래스를 상속받은 모든 자식 클래스는 반드시 추상 메서드를 오버라이딩 및 재정의하여 구현해야한다.

→ 그렇지 않으면 컴파일 에러가 발생한다.

3 추상 클래스와 추상 메서드의 용도

-자식 클래스 간의 공통적인 필드와 메서드 이름을 통일할 수 있다.

-반드시 구현해야 하는 메서드를 선언함으로써 공통 규격을 제공한다.

[추상 클래스의 용도]

-전구 규격은 동일하고 색상이나 유리 모양만 다른 것처럼, 추상 클래스는 A,B,C 클래스에 동일한 규격을 제공하고 자식 클래스들은 각각

독립적인 메서드를 가질 수 있다.


02 인터페이스 구현

-모든 메서드가 추상 메서드인 일종의 추상 클래스를 우리는 '인터페이스'라고 부른다.

-인터페이스는 추상 메서드와 상수로만 이루어져 있으며, 추상 클래스와 마찬가지로 스스로 객체를 생성할 수 없다.

-언뜻 보면 인터페이스와 추상 클래스가 같은 역할을 하는 것처럼 느껴질 수 있지만, 취지는 완전히 다르다.

[추상 클래스]

-클래스들의 공통 메서드를 추출해 선언하며, 자식 클래스들이 상속(extends)받아 구현하도록 합니다.

-(자식 클래스들에게 기본 틀과 공통 기능을 제공)

[인터페이스]

-구현 클래스들의 기본 틀을 제공하면서, 다른 클래스 코드들과의 사이에서 중간 매개 역할을 한다.

-추상 클래스는 자식 클래스들의 공통적 특징을 추출하고 제공하는 것이 주된 역할이었다면, 인터페이스는 그뿐 아니라 다른 클래스 코드들과의

중간 매개 역할을 하는 것을 중점으로 생각할 수 있다.

1 인터페이스 선

-인터페이스는 클래스가 아니다.!

-클래스는 객체를 만들기 위한 설계도 역할을 하는 코드의 블록을 클래스라고 부른다.

-추상 클래스는 스스로 객체를 생성할 수는 없지만, 자식 클래스의 생성자를 통해 객체를 생성해낼 수 있었다.

-하지만 인터페이스는 어떤 형태로도 객체를 만들 수 없기 때문에 클래스라고 부를 수 없다.

[인터페이스 선언 방법]

 

[접근 제한자] interface 인터페이스이름 {
   …
   접근 제한자 abstract 메서드이름(매개변수1, 매개변수2, …) 
  …
}

-인터페이스는 필드와 생성자를 가지지 않느다.

-이는, 객체를 생성할 수 없기에, 필드에 값을 수정할 수도 없고 생성자도 필요 없기 때문이다.

-인터페이스는 오직 추상 메서드와 상수만을 포함할 수 있다.

-인터페이스를 선언하는 방법은 클래스를 작성하는 방법과 동일하며 class 키워드 대신 interface를 작성한다.

-또한 인터페이스의 추상 메서드는 다른 클래스들과의 매개체 역할을 하므로 누구나 접근할 수 있어야한다.

-그래서 항상 public으로 구현해야 한다.

-만약 접근 제한자를 default로 구현했다면 자동으로 public으로 인식한다.

-클래스와 달리 인터페이스의 모든 필드는 public/static/final 이어야하며, 모든 메서드는 public/ static 이어야 한다.

상수 선언

-인터페이스에서는 필드 대신 상수를 선언할 수 있어야한다.

-단, 상수이기 때문에 인터페이스는 고정된 값만 선언할 수 있어 충분히 고민하고 선언해야한다.

[상수 선언 방법]

 

◈특징

-public : 인터페이스는 다른 클래스들의 접근이 가능해야 하므로 public 을 작성한다.

-static : 객체가 생성되지 않는 인터페이스기때문에, 내부 상수에 접근하려면 클래스 변수처럼 static으로 선언되어 메모리에 올라가있어야한다.

-final : 상수를 뜻하는 키워드이다.

[상수 명명 규칙]

-영문 대문자로 작성해야한다.

-2개 이상의 단어를 조합할 때는 언더바(_)로 연결한다.


03 인터페이스 사용

-추상 클래스는 앞에서 확인한 것처럼 추상 메서드가 비어있기 때문에 객체 생성을 스스로 할 수 없다.

-대신 자식 클래스의 생성자의 힘을 빌려 객체 생성을 할 수 있었다.

-추상 클래스와 마찬가지로, 인터페이스 역시 추상 메서드가 비어있기 때문에 객체 생성을 스스로 할 수 없다.

-따라서 인터페이스도 자신이 가지고 있는 추상 메서드를 구현해 줄 클래스를 작성해야한다.

-이렇게 인터페이스를 구현해 주는 클래스를 '구현 클래스'라고 한다.

-추상 클래스는 자식 클래스들이 상속받아 구현하지만, 인터페이스에서는 구현된 멤버들을 상속받는 의미가 아니기 때문에

상속이라는 단어를 사용하지 않는다.

-따라서 자식/부모 클래스라는 용어도 사용하지 않는다.

-"구현한다"라고 한다.

-구현 클래스는 인터페이스를 사용해 구현하겠다는 선언을 해야한다.

-구현한다는 의미를 가지고 있는 implements 키워드를 사용하여 명시할 수 있다.

-인터페이스의 모든 추상 메서드를 오버라이딩하지 않으면 에러가 발생한다.

-즉, 인터페이스를 구현하려면 모든 추상 메서드를 구현해야한다.

-만약 추상 메서드를 오버라이딩한 메서드의 접근 제한자를 public으로 지정하지 않으면 에러가 발생한다.

-즉, 구현 클래스에서 추상 메서드를 구현할 때는 반드시 접근 제한자를 public으로 지정해야한다.

-인터페이스의 상수를 가져와 사용하려면 호출해야한다.

▶인터페이스 이름.상수 이름

[인터 페이스 장점]

▷실제 구현 클래스의 내용을 전혀 보지 않고도 개발 코드로 객체를 사용할 수 있다. => 정보 은닉

▷구현 클래스들이 독립적으로 구현되고 사용될 수 있다.

개발 코드에서 객체 변경이 필요할 때, 개발 코드의 수정을 최소화할 수 있다. => 모듈화

[추상 클래싀와 인터페이스의 공통점]

▷추상 클래스와 인터페이스는 각각의 장점을 가지고 있지만, 사실 서로의 장점을 공유하기도 한다.

▷정보 은닉, 모듈화, 추상화 등은 추상 클래스와 인터페이스가 공통으로 가진 장점이다.

▷추상 클래스의 특징이 추상화와 모듈화에 중점을 맞췄다면, 인터페이스는 추상화의 특징을 가지고 있지만 정보 은닉과 모듈화에

좀 더 초점을 맞췄다고 할 수 있다.

▷추상 클래스와 인터페이스 모두 다형성을 구현할 수 있는 기반을 제공하며, 추상 메서드 구현에 대한 강제성을 반영하고 있다.

다중 인터페이스 구현

-하나의 클래스로 여러 개의 인터페이스를 구현할 수 있다.

-다중 인터페이스를 선언하는 방법은 간단하다.

-implements 키워드 뒤에 인터페이스 이름을 기재할 때 콤마(,)를 이용해 여러 개를 붙여 선언한다.

-단, 선언한 모든 인터페이스에 대한 추상 메서드를 모두 구현해야한다.

 


04 인터페이스 상속

-인터페이스끼리 상속 관계를 만들 수 있다.

-클래스의 상속과 마찬가지로 extends 키워드를 사용하며, 다중 상속이 가능하기 때문에 콤마(,)를 이용한다.

-클래스의 상속과 마찬가지로 인터페이스 상속을 선언하면, 하위 클래스는 상위 클래스의 모든 멤버를 상속받게 된다.

-만약 하위 인터페이스를 구현하는 클래스가 있다면, 해당 클래스는 하위 인터페이스의 추상 메서드를 포함하여

상위 인터페이스의 추상 메서드까지 구현해야한다.