본문 바로가기

프로그래밍/JAVA

[JAVA 이론] 클래스(추상, 인터페이스, 내부, 익명)

추상클래스

추상클래스는 미완성 된 클래스이다. 따라서,

 

추상클래스 특징

1. 추상클래스로 인스턴스는 생성할 수 없다

2. 추상클래스는 상속을 통해서 자손클래스에 의해서만 완성 될 수 있다.

3. 추상클래스 자체로는 클래스로서의 역할을 다 못하지만, 새로운 클래스를 작성하는데 있어서 바탕이 되는 조상클래스로서 중요한 의미를 갖는다.

4. 새로운 클래스를 작성할 때 아무 것도 없는 상태에서 시작하는 것보다는 완전하지는 못하더라도 어느 정도 틀을 갖추게 해준다.

 

추상메서드

선언부만 작성하고 구현부는 작성하지 않은 채로 남겨 둔 것이 추상메서드이다.

 

추상메서드 특징

1. 미완성 상태로 남겨 놓는 이유는 메서드의 내용이 상속받은 클래스에 따라 달라질 수 있기 때문이다.

2. 조상 클래스에서는 선언부만 작성하고, 주석을 덧붙여 어떤 기능을 수행할 목적으로 작성되었는지 알려준다.

3. 실제 내용은 상속받은 클래스에서 구현하도록 비워 둔다.

4. 추상클래스로부터 상속받는 자손클래스는 오버라이딩을 통해 조상인 추상클래스의 추상 메서드를 모두 구현해주어야 한다. 만일 조상으로부터 상속받은 추상메서드 중 하나라도 구현하지 않는다면, 자손클래스 역시 추상클래스로 지정

/* 주석을 통해 어떤 기능을 수행할 목적으로 작성하였는지 설명한다. */
abstract 리턴타입 메서드이름();

 

추상클래스의 작성

여러 클래스에 공통적으로 사용될 수 있는 클래스를 바로 작성하기도 하고, 기존의 클래스의 공통적인 부분을 뽑아서 추상클래스로 만들어 상속하도록 하는 경우도 있다.

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

추상메서드로 선언하는 이유는 자손 클래스에서 추상메서드를 반드시 구현하도록 강요하기 위해서이다.

조상 클래스타입의 참조변수로 자손 클래스의 인스턴스를 참조하는 것이 가능하기 때문에 조상 클래스타입의 배열에 자손 클래스의 인스턴스를 담을 수 있는 것이다.

Army[] army = new Army[3];
army[0] = new tank();
army[1] = new warship();
army[2] = new plane();

for(int i = 0; i < army.length; i++)
	army[i].move(100, 200);

 

인터페이스

인터페이스는 일종의 추상클래스이다.

 

인터페이스의 특징

1. 추상화클래스보다 추상화 정도가 높아다

2. 추상메서드와 상수만을 멤버로 가질 수 있으며, 그 외에 다른 어떠한 요소도 허용하지 않는다.

3. 인터페이스는 그 자체만으로 사용되기 보다는 다른 클래스를 작성하는데 도움 줄 목적으로 작성 된다.

 

인터페이스의 작성

인터페이스를 작성하는 것은 클래스를 작성하는 것과 같다. 다만 키워드로 class 대신 interface를 사용한다는 것만 다르다. 그리고 interface에도 클래스와 같이 접근제어자로 public 또는 default를 사용할 수 있다.

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

- 모든 멤버변수는 public static final 이어야 하며, 이를 생략할 수 있다.

- 모든 메서드는 public abstract 이어야 하며, 이를 생략할 수 있다.

  단, static메서드와 디폴트 메서드는 예외(JDK1.8부터)

interface Interface{
	int variable = 1; //public static final int variable = 1; 
}

 

인터페이스의 상속

1. 인터페이스는 인터페이스로부터만 상속받을 수 있으며, 클래스와는 달리 다중상속, 즉 여러 개의 인터페이스로부터 상속을 받는 것이 가능하다.

2. 클래스의 상소과 마찬가지로 자손 인터페이스는 조상 인터페이스에 정의된 멤버를 모두 상속받는다.

cf) 인터페이스는 클래스와 달리 Object클래스와 같은 최고 조상이 없다.

 

인터페이스의 구현

1. 인터페이스도 추상클래스처럼 그자체로는 인스턴스를 생성할 수 없다

2. 자신에 정의된 추상메서드의 몸통을 만들어주는 클래스를 작성해야 한다.

3. 상속시 extends 대신 implements를 사용한다.

class 클래스이름 implements 인터페이스이름{
	// 인터페이스에 정의된 추상메서드를 구현해야 한다.
}

만일 구현하는 인터페이스의 메서드 중 일부만 구현한다면, abstract를 붙여서 추상클래스로 선언해야 한다. 상속과 구현을 동시에 할 수 도 있다.

 

인터페이스의 다중상속

인터페이스를 통해 다중 상속은 가능하지만 자바에서는 인터페이스로 다중상속을 구현하는 경우는 거의 없다.

 

인터페이스는 static상수만 정의할 수 있으므로 조상클래스의 멤버변수와 충돌하는 경우는 거의 없고 충돌된다 하더라도 클래스 이름을 붙여서 구분이 가능하다. 그리고 추상메서드는 구현내용이 전혀 없으므로 조상클래스의 메서드와 선언부가 일치하는 경우에는 당연히 조상 클래스 쪽의 메서드를 상속받으면 되므로 문제되지 않는다. 

 

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

인터페이스 역시 이를 구현한 클래스의 조상이라 할 수 있으므로 해당 인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스를 참조할 수 있으며, 인터페이스 타입으로의 형변환도 가능하다.

Fightable f = (Fightable)new Fighter();
또는
Fightable f = new Fighter();

 

인터페이스는 메서드의 매개변수의 타입으로 사용 될 수 있다.

void attack(Fightable){
	//...
}

인터페이스 타입의 매개변수가 갖는 의미는 메서드 호출 시 해당 인터페이스를 구현한 클래스의 인스턴스를 매개변수로 제공해야한다는 것이다.

리턴타입이 인터페이스라는 것은 메서드가 해당 인터페이스를 구현한 클래스의 인스턴스를 반환한다는 것을 의미한다.

 

인터페이스의 장점

  1. 개발시간을 단축시킬 수 있다.
    인터페이스가 작성되면, 이를 사용해서 프로그램을 작성하는 것이 가능하다.
  2. 표준화가 가능하다.
  3. 서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다.
  4. 독립적인 프로그래밍이 가능하다.
    인터페이스를 이용하면 클래스의 선언과 구현을 분리시킬 수 있기 때문에 실제구현에 독립적인 프로그램을 작성하는 것이 가능하다.

인터페이스의 이해

- 클래스를 사용하는 쪽(User)과 클래스를 제공하는 쪽(Provider)이 있다.

- 메서드를 사용(호출)하는 쪽(User)에서는 사용할여는 메서드(Provider)의 선언부만 알면 된다.(내용은 몰라도 된다.)

 

클래스 A(User)가 B(Provider)의 인스턴스를 생성하고 메서드를 호출한다면, 이 두클래스는 서로 직접적인 관계가 있다.

이 경우 클래스 A를 작성하려면 클래스 B가 이미 작성되어 있어야 한다. 그리고 클래스 B의 메서드의 선언부가 변경되면, 이를 사용하는 클래스 A도 변경되어야 한다.

그러나 클래스 A가 클래스 B를 직접 호출하지 않고 인터페이스를 매개체로 해서 클래스A가 인터페이스를 통해서 클래스 B의 메서드에 접근하도록 하면, 클래스 B에 변경사항이 생기거나 클래스 B와 같은 기능의 다른 클래스로 대체 되어도 클래스 A는 전혀 영향을 받지 않도록 하는 것이 가능하다.

//변경 전
class A{
	public void methodA(B b){
		b.methodB();
	}
}

//변경 후
class A{
	public void methodA(I i){
		i.methodB();
	}
}

 

디폴트 메서드와 static메서드

원래는 인터페이스에 추상 메서드만 선언할 수 있는데, JDK1.8부터 디폴트 메서드와 static메서드도 추가할 수 있게 됨

 

- static메서드

static 메서드는 인스턴스와 관계가 없는 독립적인 메서드이기 때문에 인터페이스에 추가하지 못할 이유가 없음

 

- 디폴트 메서드

인터페이스에 메서드를 추가한다는 것은, 추상메서드를 추가한다는 것이고, 이 인터페이스를 구현한 기존의 모든 클래스들이 새로 추가된 메서드를 구현해야하기 때문에 일이 커진다.

디폴트 메서드는 추상 메서드의 기본적인 구현을 제공하는 메서드로, 추상 메서드가 아니기 때문에 디폴트 메서드가 새로 추가되어도 해당 인터페이스를 구현한 클래스를 변경하지 않아도 된다.

//디폴트 메서드와 기존의 메서드의 이름 충돌 경우 규칙
1. 여러 인터페이스의 디폴트 메서드 간의 충돌
   - 인터페이스를 구현한 클래스에서 디폴트 메서드를 오버라이딩한다.
2. 디폴트 메서드와 조상 클래스의 메서드 간의 충돌
   - 조상 클래스의 메서드가 상속되고, 디폴트 메서드는 무시된다.

 

내부 클래스

내부 클래스는 클래스 내에 선언된 클래스이다.

 

내부 클래스의 장점

- 내부 클래스에서 외부 클래스의 멤버들을 쉽게 접근할 수 있다.

- 코드의 복잡성을 줄일 수 있다(캡슐화).

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

내부 클래스가 외부클래스의 멤버와 같이 간주 되기 때문에, 인스턴스멤버와 static멤버 간의 규칙이 내부 클래스에도 똑같이 적용된다. abstract, final, private, protected 등 접근제어자 사용이 가능

 

익명 클래스

이름이 존재하지 않는 클래스.

 

익명 클래스를 사용하는 이유는 프로그램 내에서 한번만 객체로 만드는데 사용되는 클래스를 굳이 정의할 필요가 없기 때문입니다. 이런 이유로, Runnable이나 Event Listener 객체를 생성하는데 주로 사용됩니다.

 

익명 클래스의 특징

1. 클래스의 선언과 객체의 생성을 동시에 하기 때문에 단 한번만 사용될 수 있다.

2. 오직 하나의 객체만을 생성할 수 있는 일회용 클래스이다.

3. 생성자를 가질 수 없다.

4. 오로지 단 하나의 클래스를 상속받거나 단 하나의 인터페이스만을 구현할 수 있다.

 

public class Anonymous {
	Object iv = new Object() {void method(){}};
	static Object cv = new Object(){void method(){}};
	
	void myMethod() {
		Object lv = new Object() {void method(){}};
	}
}

//컴파일
Anonymous.class
Anonymous$1.class
Anonymous$2.class
Anonymous$3.class

 

익명 클래스 예제

import java.awt.Button;
import java.awt.event.*;

public class Anonymous {
	public static void main(String[] args) {
		Button b = new Button("Start");
		b.addActionListener(new EventHandler());
	}
}

class EventHandler implements ActionListener{
		public void actionPerformed(ActionEvent e) {
			System.out.println("ActionEvent occurred!!");
		}
}
import java.awt.Button;
import java.awt.event.*;

public class Anonymous {
	public static void main(String[] args) {
		Button b = new Button("Start");
		b.addActionListener(new EventHandler() {
			public void actionPerformed(ActionEvent e) {
				{
					System.out.println("ActionEvent occurred!!");
				}
			}
		});
	}
}

'프로그래밍 > JAVA' 카테고리의 다른 글

[JAVA 이론] java.lang package & util classes  (0) 2022.01.27
[JAVA 이론] 예외처리  (0) 2022.01.27
[JAVA 이론] 다형성  (0) 2022.01.27
[JAVA 이론] 상속  (0) 2022.01.26
[JAVA 이론] 오버로딩 & 오버라이딩  (2) 2022.01.22