본문 바로가기
개발언어/Java : 자바

자바 쉽게 배우기 10 - 다양한 클래스와 인터페이스

by 개발자D 2023. 1. 21.

다양한 클래스와 인터페이스

자바의 다양한 클래스 - 추상 클래스, 내부 클래스, 익명 클래스

추상 클래스 abstract class

자바 쉽게 배우기 8 - 상속과 제어자에서 abstract 키워드에 대해 설명드렸습니다. 추상클래스는 추상메서드를 가지고 있는 클래스를 뜻합니다. 추상메서드는 구현부 {}가 없는 메서드로, 오버라이딩으로 구현부를 완성시켜야 사용할 수 있습니다.

추상클래스는 불완전한 형태이기 때문에 인스턴스를 생성할 수 없습니다. 이러한 규칙 때문에 인스턴스 생성을 제한하기 위한 용도로 추상메서드가 없는 클래스를 추상 클래스로 선언하기도 합니다.

추상클래스를 사용하기 위해서는 추상클래스를 상속받아 추상메서드를 구현하고 인스턴스를 생성합니다. 추상클래스를 상속받을 땐 extends 키워드를 사용합니다.

 

abstract class 클래스명 { // 추상 클래스
	abstract 리턴타입 메서드명(); // 추상 메서드
}

class 구현할클래스 extends 추상클래스 {
	리턴타입 구현할메서드명() { 
		// 구현할 내용 
	}
}

 

❓ 추상 클래스를 왜 사용할까요?

- 여러 개발자들이 공통된 부분을 개발할 때 같은 변수와 메서드 이름을 사용하도록 하기 위함입니다.

- 하위 구현 클래스에서 공통적으로 사용할 변수와 메서드를 추상 클래스에 구현해 놓으면 시간을 절약할 수 있습니다.

 

내부 클래스 inner class / 중첩 클래스 nested class

내부 클래스는 이름처럼 클래스 내부에 있는 클래스를 의미합니다. 내부 클래스는 내부클래스에서는 내부클래스를 감싸고 있는 클래스의 멤버에 인스턴스 생성 없이 접근할 수 있습니다. 내부 클래스는 선언 위치에 따라 종류가 나뉘며 선언 위치는 변수의 선언 위치와 유사합니다.

 

❓ 내부 클래스를 왜 사용할까요?

클래스가 긴밀하게 연결되어 있을 때 서로의 멤버 간 접근성을 높이기 위해 사용합니다.

내부 클래스의 종류와 특징

종류 위치 사용 목적
인스턴스 클래스 감싸는 클래스의 멤버변수 선언 자리
인스턴스 멤버처럼 취급
인스턴스 멤버와 관련된 작업에 사용
스태틱 클래스 감싸는 클래스의 멤버변수 선언 자리
스태틱 멤버처럼 취급
스태틱 멤버와 관련된 작업에 사용
지역 클래스 감싸는 클래스의 메서드, 초기화 블럭 자리 메서드나 초기화 블럭이 실행될 때 사용
익명 클래스 모든 위치 클래스를 만들고, 인스턴스를 생성하는 것을 간략화 하기 위한 용도로 사용
이름이 없기 때문에 한 번 사용되고 말 인스턴스를 만드는 데 사용
  • 내부 클래스를 중첩 클래스라고 부르며, 스태틱 클래스를 내부 클래스로 인정하지 않고 나머지 클래스만 내부 클래스로 구분하는 의견도 있습니다.
  • 내부 클래스와 감싸는 클래스에 같은 이름의 변수가 있다면
    감싸는 클래스의 변수는 감싸는클래스명.this.를 붙이고 내부 클래스의 변수는 this. 를 붙여 구분합니다. 

 

감싸는 클래스의 외부에서 내부 클래스의 인스턴스를 만드는 법

 

class A {
	class B {
    }
}

// 인스턴스 클래스
A a = new A();
A.B b = a.new B();

// 스태틱 클래스
A.B b = new A.B();

 

내부 클래스의 인스턴스는 감싸는 클래스의 외부에서 사용될 일이 없는 게 좋습니다.

 

익명클래스 / 익명 객체

이름이 없는 클래스로 클래스의 선언과 인스턴스 생성이 동시에 이루어집니다. 상속받거나 구현할 클래스의 인스턴스를 만드는 데 사용됩니다. 상위 클래스나 인터페이스의 이름을 사용해 정의하기 때문에 상속과 구현을 동시에 하거나, 다중 구현을 할 수 없습니다.

 

new 상위클래스명() {...}
new 인터페이스명() {...}

// ... 위치에 일반적인 클래스처럼 멤버 변수와 메서드를 선언할 수 있습니다.
// 익명 클래스는 이름이 없기 때문에 생성자 선언은 불가능합니다.

 

❓ 익명 클래스를 왜 사용할까요?

한 번 사용할 인스턴스를 만드는 데 구현 클래스를 정의하는 것이 비효율적이기 때문입니다.

 


인터페이스 interface

인터페이스는 엄격한 추상화 클래스로 이해할 수 있습니다. 추상화 클래스에서는 일반 변수와 메서드가 있어도, 심지어 추상화 메서드가 없어도 추상화 클래스가 될 수 있었습니다. 하지만 인터페이스는 오로지 추상 메서드상수만을 멤버로 가질 수 있습니다.

인터페이스는 큰 틀을 잡는 설계도라고 할 수 있습니다. 인터페이스를 통해 어떤 상수와 메서드를 사용할 것인지 가이드를 잡아 놓는 것입니다. 협업하는 개발자들은 같은 인터페이스를 구현하면서 동일한 이름과 형식(제어자, 리턴타입, 매개변수 개수 등)의 상수와 메서드를 사용하게 됩니다. 따라서 불필요한 취합 과정을 거치지 않아도 됩니다. 또한 이미 선언된 인터페이스의 멤버를 사용하여 구현되지 않은 부분을 기다리지 않고도 자신이 맡은 파트를 독립적으로 구현해 낼 수 있습니다.

 

interface 인터페이스명 {
    public static final 타입 상수명 = 값;
    public abstract 메서드명(매개변수들);
}

// 제어자는 생략할 수 있습니다.
// JDK1.8부터 인터페이스에서 static메서드와 디폴트 메서드의 사용이 가능해졌습니다.

 

❓ 디폴트 메서드(default method) 란 무엇인가요?

디폴트 메서드는 인터페이스에 선언하는 구현부가 있는 메서드입니다. default 키워드를 앞에 붙여 사용하며, 하위 호환성을 위해 사용합니다. 만약 디폴트 메서드를 사용할 수 없는 경우에 interface에 새로운 메서드를 추가하게 되면 interface를 구현하는 모든 클래스들이 새로운 메서드를 구현해야 하는 부담을 안게 됩니다. 이를 해결하고자 default 메서드가 추가되었습니다. default 메서드는 이미 구현되어 있기 때문에 구현 클래스에서 구현하지 않아도 됩니다.

 

인터페이스는 상속하지 않고 구현하여 사용합니다. 따라서 상속의 extends 키워드가 아닌 implements 키워드를 사용합니다. 인터페이스는 클래스와 달리 다중 구현이 가능합니다. 클래스를 상속받으면서 동시에 인터페이스를 구현하는 것도 가능합니다. 인터페이스끼리는 상속이 가능합니다. (다중 상속도 가능합니다)

// 인터페이스 구현
class 클래스명 implements 인터페이스명

// 인터페이스 다중 구현
class 클래스명 implements 인터페이스명, 인터페이스명, ...

// 클래스 상속 + 인터페이스 구현
class 클래스명 extends 상위클래스명 implements 인터페이스명

// 인터페이스끼리의 상속
interface 인터페이스명 extends 인터페이스명

// 인터페이스끼리의 다중 상속
interface 인터페이스명 extends 인터페이스명, 인터페이스명, ...

 

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

다형성은  '여러 가지 형태를 가질 수 있는 능력'으로 하위클래스의 인스턴스가 상위클래스의 타입으로 선언되는 것이었습니다. 이를 다양한 방법으로 활용하기 위해서 참조변수의 형변환을 사용했죠. 형변환을 통해 사용가능한 멤버의 범위를 조절했습니다. 

 [인터페이스와 구현클래스]도 [상위클래스와 하위클래스]와 유사한 관계를 갖습니다. 즉, 구현클래스의 인스턴스는 인터페이스 타입으로 선언되거나, 형변환하는 것이 가능합니다. 인터페이스 타입의 매개변수와 리턴타입은 해당 인터페이스를 구현한 클래스의 인스턴스를 의미합니다.


객체 지향 프로그래밍의 핵심인 상속과 구현이 끝났습니다. 다음 글에서는 자바에서 예외를 처리하는 방법에 대해 알아봅시다.

 

자바 쉽게 배우기 11 - 예외 처리

예외 한 번에 완벽한 코드를 짤 수 있다면 얼마나 좋을까요? 하지만 그것은 환상에 가깝습니다. 항상 수많은 에러들이 프로그래머들을 기다리고 있습니다. 에러를 수정하는 일은 프로그래머들

devdharu.tistory.com