포스트

21. 인터페이스와 추상 클래스

인터페이스와 추상 클래스에 대해 알아가보자.

21. 인터페이스와 추상 클래스

Interface(= 인터페이스)

인터페이스는 사용 규칙을 정의해주는 틀이라고 보면된다.

인터페이스

인터페이스는 틀을 짜주는 도구이기 때문에 메서드 시그니처 형식</sapn>으로 작성을 한다.

1
2
public void add(Object value) // method signature 메서드 시그니처
{ - }                         // method body 메서드 바디

이렇게 메서드 시그니처 형식으로만 작성되고 바디는 작성되지 않은 형태</sapn>를 추상 메서드라고 하고 주로 인터페이스와 추상 클래스에 사용이 된다.

추상 메서드

인터페이스는 모든 메서드를 암묵적으로 추상 메서드로 사용하는데 추상 메서드는 기본 public이여야하고 abstract 키워드를 사용하여 선언해야한다.

1
2
3
4
5
6
7
8
public interface List{
	public abstract void add(Object value); // 추상메서드는 기본 public 과 abstract를 포함한다.
	public Object remove(int index);        // 인터페이스는 모든 메서드를 암묵적으로 추상 메서드라고 본다.
	abstract Object get(int index);         // 그래서 public이나 abstract를 굳이 껴 넣지 않아도 오류가 나지 않고
	Object[] toArray();                     // 자동으로 public과 abstract를 포함하고 있다고 생각하면 된다
	
	private void test();                    // 이러한 형태는 오류를 일으킨다.
}

인터페이스 사용

위처럼 설정한 인터페이스를 사용하기 위해선…

  1. implemeantes ~ 를 사용하여 클래스에 받아와야하며
  2. @Override 주석을 통해 오버라이드해 사용해야한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
class ArrayList implemeantes List{
	@Override
	public void add(Object value){ ~ }
	
  @Override
  public Object get(int index) { ~ }
  
  @Override
  public Object remove(int index){ ~ }
  
  @Override
  public Object[] toArray(){ ~ }
}

만약 Override를 했는데

  1. 인터페이스에 관련된 추상 메서드 이름이 없는 경우
  2. 인터페이스에는 존재하는 추상 메서드를 본문 클래스에서 구현하지 않았을 경우 에러가 나게 된다.

인터페이스를 왜 쓰는건가

인인터페이스 사용 1

인터페이스는 틀이다. 인터페이스를 만들어두면 클래스의 규칙을 정의해두는건데…
이런 규칙이 있다면 추후 비슷한 기능의 클래스를 만들 때 일관성 있는 프로그래밍을 가져갈 수 있고
만약 해당 클래스를 상속받아 사용하는 서브 클래스에서 코드 변경없이 부모 클래스 변경만으로 간단하게 비슷하지만 다른 기능을 가져갈 수 있다.

인터페이스 사용 2 우리의 실습 프로젝트에 대입해서 보자면 이런 느낌..?

instanceof 와 getClass

인텔리제이
equals를 오버라이딩 할 때 인텔리J에서는 선택지를 제공해준다.

이 차이를 살펴보자

추상클래스

User를 상속받은 Manager class가 있다고 할때…

  1. getClass

    1
    2
    3
    4
    5
    
     equals(Object object){
     	if(this.getClass() != obj.getClass()){
     		return false;
     	}
     }
    
  2. instanceof

    1
    2
    3
    4
    5
    
     equals(Object object){
     	if(obj instanceof User){
     		return false;
     	}
     }
    
1
2
3
4
5
6
7
8
9
10
User u1 = new User();
String str = new String();
User u2 = new User();
Manager m = new Manager();

u1.equals(str);   // getClass : F / instanceof : F
u1.equals(u2);    // getClass : T / instanceof : T
u1.equals(m);     // getClass : F / instanceof : T << 다른 결과가 나온다.

// 명확하게 해당 클래스인지를 확인하고 싶다면 getClass를 사용해 비교하는 것이 맞다. < 이 방법이 자주 사용된다.

추상 클래스

추상클래스는 인터페이스에 작성된 규칙이 어떤 곳이든 동일하게 바디가 작성이 될 때,
중복된 코드하나로 합쳐주기 위해 사용된다.

추상 클래스

추상 클래스의 사용

1
2
3
4
5
6
7
8
9
// public class AbstractList implements List <- abstract가 붙지 않으면 List에 포함된 모든 메서드들이 정의 되지않아 에러를 일으킨다.
public abstract class AbstractList implements List {  // 그래서 클래스 앞에 반드시 abstract가 붙어야한다.
    protected int size = 0;

    @Override
    public int size() {
        return size;
    }
}

이렇게 만든 추상 클래스를 사용하기 위해선..

1
public class LinkedList extends AbstractList { - } // 추상 클래스를 상속 받으면 List 인터페이스와 추상 클래스를 모두 가지고 있는 클래스가 된다.

중첩 클래스

중첩 클래스 중 static nested class만 오늘 잠깐 알아보자.
LinkedList 클래스를 위해 Node 클래스를 하나 만들었는데 이 Node 클래스는 LinkedList에서만 사용이 된다.
내부적으로 가지고 있는 인스턴스 멤버도 없기 때문에 독립성을 가지기 위해 LinkedList로 옮긴 후 static을 붙여 중첩 클래스로 만들어 준다.

중첩 클래스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class LinkedList extends AbstractList {
	private Node first;
	private Node last;
    
  // Node 클래스는 위처럼 LinkedList에만 속하고 사용되기 때문에 안에 넣고 static을 붙여 독립성을 가져준다.
	private static class Node {
		Object value;
    Node next;

    public Node(Object value){
	    this.value = value;
    }
	}
}
짤지식
  • UML(= Unified Modeling Language / 유니파이드 모델링 랭귀지)

클래스 멤버

클래스 멤버란?
클래스에 속하는 변수나 메서드를 의미한다.

  • 클래스 멤버
    • 필드(= 변수)
      • static(= 클래스 필드)
      • non-static(= 인스턴스 필드)
    • 메서드
      • static(= 클래스 메서드)
      • non-static(= 인스턴스 메서드)
    • 생성자
    • 초기화 블록(initializer)
      • static
      • 인스턴스
    • 중첩 클래스(= nested class)
      • static
      • non-static(= innerclass)

인스턴스 필드

1
2
3
4
5
class A{
	int v1;
	boolean v2;
}
	A obj = new A(); // 200 주소 -> heap에 올라감 200[ v1 = 0 | v2 = false ]

클래스 로딩

클래스 로딩

static field의 초기화 동작

스태틱 필드 초기화 동작 com.eomcs.oop.ex03.Exam0691 예제 동작 확인

  • 스태틱 필드는 클래스를 로딩할 때 모두 불러온다.
  • 위 이미지에서 A 클래스에서 a += B.b를 실행할 때 B클래스의 스태틱 필드를 모두 불러오면서 B클래스의 b += A.a를 먼저 실행 후 A 클래스의 문을 실행하게된다.
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.