인터페이스(Interface)

 

- 추상 메소드들로만 이루어진 형태로, 객체의 사용 방법을 정의한 새로운 타입이다.

 

- 상수 외에 필드를 선언할 수 없다.

 

- 자바에서 인터페이스란 객체와 객체 사이의 상호 작용이 이루어지는 인터페이스이다.

 

- 추상 메소드의 성질을 이용하면, 인터페이스는 여러 객체들과 사용이 가능하므로 어떤 객체를 사용하느냐에 따라 실행 내용과 리턴값이 다를 수 있다.

 

- , 개발 코드를 수정하지 않고 사용하는 객체만 변경하여 메소드를 실행한다.

 

- 객체의 교환성을 높여주기 때문에 다형성을 구현하는 매우 중요한 역할을 한다.

 

상속은 같은 종류의 하위 클래스를 만드는 기술이고, 인터페이스는 사용 방법이 동일한 클래스를 만든다는 점에서 개념적인 차이가 있다. 그러나 둘 다 다형성을 구현하는 기술이다.


- 인터페이스를 구현하는 객체를 구현 객체라고 부르며, 구현 객체를 생성하는 클래스를 구현 클래스라고 부른다. 구현 클래스는 추상 메소드의 몸체를 반드시 구현하여야 한다.

 

- 인터페이스의 모든 메소드는 기본적으로 public 접근 제한자를 갖기 때문에 구현 클래스에서 작성할 때 public 보다 더 강한 접근 제한자(default, private )를 사용할 수 없다. , public을 생략해선 안된다.

 

- 상속과는 달리 구현 클래스는 다수의 인터페이스를 구현할 수 있다.

 

- 인터페이스끼리는 상속이 가능하다.

public interface 인터페이스1 extends 인터페이스2 { ... }

 

- 구현 클래스는 선언부에 implements 키워드를 추가하고 인터페이스 명을 명시해야 한다.

* implements 시행하다, 도구라는 뜻이다.

 

- 인터페이스 타입의 변수는 참조형 변수이기 때문에 구현 객체가 대입될 경우 구현 객체의 번지를 저장한다.


 


인터페이스의 구성 멤버

 

- 상수 필드 : 상수는 인터페이스에 고정된 값이므로 런타임 시에 데이터를 바꿀 수 없다. 상수를 선언할 때에는 반드시 초기값을 대입해야 한다.


public static final 자료형 변수명;


 

- 추상 메소드 : 객체가 사용할 메소드의 형태를 설명한 것으로, 어ᄄᅠᆫ 매개값이 필요하고 리턴 타입이 무엇인지만 알려준다. 실체 실행부는 해당 인터페이스를 구현하는 클래스에서 작성해야 한다.

 

- 디폴트 메소드 : 자바 8버전에서만 허용하는 멤버이며, 기존 인터페이스를 확장해서 사용하기 위함이다. 선언할 때 인터페이스를 구현한 실제 객체가 가지고 있는 메소드라고 생각하면 된다. 따라서 구현 객체에서는 인터페이스의 디폴트 메소드의 실체 메소드를 작성할 필요가 없다.

 

- 정적 메소드 : 자바 8버전에서만 허용하는 멤버이며, 디폴트 메소드와 달리 객체가 없어도 인터페이스만으로 호출이 가능하다. 쉽게 말해, 인터페이스를 선언하지 않고 "인터페이스이름.정적메소드명()"과 같이 바로 호출이 가능함.

 

 

 

인터페이스의 일반적인 형태

 

- 인터페이스의 모든 메소드는 추상 메소드로 간주되므로 abstract키워드는 사용하지 않는다.

 


public interface 인터페이스명 {

//상수

...

 

//추상 메소드

리턴타입 추상메소드1(...);

리턴타입 추상메소드2(...);

...


//디폴트 메소드 -> default를 붙여야한다. 안 붙이면 추상 메소드로 간주됨

default 리턴타입 메소드명(...) { ... }

...


//정적 메소드

static 리턴타입 메소드명(...) { ... }

}




public class 클래스명 implements 인터페이스명 {

 

//FIELDS

...

 

//CONSTRUCTOR

...

 

//METHODS

@Override

리턴타입 추상메소드1(...) {

    ...

}


@Override

리턴타입 추상메소드2(...) {

    ...

}

 

} 


- @Override 란 인터페이스의 추상 메소드에 대한 정확한 실체 메소드인지 컴파일러가 체크하도록 지시하는 어노테이션이다. 생략해도 상관없으나, 실체 메소드가 잘못되지 않도록 해주기 때문에 붙여 주는 것이 좋다.




▶ 인터페이스의 타입 변환


- 구현 객체가 인터페이스 타입으로 변환되는 것은 자동 타입 변환에 해당한다. 이렇게 자동 타입 변환된 구현 객체는 해당 클래스의 필드와 메소드를 사용할 수 없다. 즉, 인터페이스의 상수와 메소드만 사용가능하다.


- 반대로, 인터페이스 타입인 구현 객체를 강제 타입 변환하여 구현 클래스 타입으로 사용할 수 있다.


- 필드와 매개변수의 타입을 인터페이스로 선언하면 여러 구현 객체를 대입하여 다양한 실행 결과를 만들 수 있다.


 

 

* 상속


- 자바에서 상속이란 부모 클래스의 멤버를 자식 클래스에게 물려주는 행위이다.


- 프로그램에서는 자식 클래스가 부모 클래스를 선택하며 클래스명 뒤에 “extends 부모 클래스명를 기술하여 사용한다.


- , 다중 상속은 허용하지 않는다.

 

class 자식클래스명 extends 부모클래스1, 부모클래스2 --> 절대 X

 

- 다른 패키지의 클래스를 상속할 경우 패키지명.클래스명을 import해야한다.

상속의 장점


- 상속은 이미 개발된 클래스를 재사용하여 새로운 클래스를 만들기 때문에 코드의 중복을 줄여준다.


- 상속을 이용하여 클래스의 수정을 최소화할 수 있다. , 유지 보수 시간을 최소화한다.


package sec.example;

 

public class A {

int field1;

 

void method1() { ... }    

}

 

public class B extends A { //A를 상속함

String field2;

 

void method2() { ... }

}



 

상속 가능 범위


- 부모 클래스에서 private 접근 제한을 갖는 멤버들(필드와 메소드)은 상속 대상에서 제외된다.


- 부모 클래스와 자식 클래스가 서로 다른 패키지일 때 부모 클래스의 default 접근 제한을 갖는 멤버들도 상속 대상에서 제외된다.


- 그 외에 상속한 클래스의 필드와 메소드는 자식 클래스에서 자유롭게 사용할 수 있다.


B b = new B();

//A로부터 물려받은 필드와 메소드

b.field1 = 10;

b.method1();

 

//B가 추가한 필드와 메소드

b.field2 = "홍길동“;

b.method2();



 

* 부모 생성자의 호출


- 자식 객체를 생성하면, 부모 객체가 먼저 생성되고 그 다음에 자식 객체가 생성된다. 마치, 부모 없는 자식이 없는 것처럼 말이다.


- 부모 생성자는 자식 생성자의 맨 첫줄에서 super() 키워드를 통해 호출된다. 생성자가 명시적으로 선언되지 않았다면 컴파일러는 디폴트 생성자에 super(); 키워드를 맨 앞에 추가하여 생성해 낸다. 여기서 super(매개변수); 는 부모 생성자 역할을 한다.


- super의 매개변수는 부모 생성자의 매개변수의 형태와 동일해야한다.

 

 

* 메소드의 재정의(Overriding)


- 어떤 메소드는 상속받은 자식 클래스에서 사용하기에 부적합할 수도 있다. 이 문제를 해결하고자 상속된 일부 메소드는 자식 클래스에서 다시 수정해서 사용할 수 있다. , 자식 클래스에서 부모 클래스의 메소드와 동일한 메소드를 재정의하는 것을 말한다.


- 재정의할 메소드 위에는 @Override 키워드가 있어야 한다.


- 메소드가 오버라이딩되면 부모 객체의 메소드는 숨겨지기 때문에 자식 객체에서 메소드를 호출하면 오버라이딩된 자식 객체가 호출된다.


- 그러나 간혹, 숨겨진 부모 객체의 메소드를 사용해야 할 때가 있다면, super 키워드를 이용하여 호출할 수 있다.


 super.부모메소드();



- 메소드 오버라이딩 규칙

  • 부모의 메소드와 동일한 구조(리턴 타입, 메소드 이름, 매개 변수 리스트)를 가져야 한다.
  • 접근 제한을 더욱 강하게 오버라이딩 할 수 없다.
  • (상속된 부모 객체의 메소드가 default일 때 private로 바꿀 수 없으며, public으로는 가능하다.)
  • 새로운 예외(Exception)throws 할 수 없다.

 


final 클래스와 final 메소드


- 상속할 수 없는 final 클래스 : 클래스 선언 시 아래와 같이 class 앞에 final 키워드를 붙이게 되면 이 클래스는 최종적인 클래스이므로 상속할 수 없는 클래스가 된다. , final 클래스는 부모 클래스가 될 수 없다.


public final class 클래스명 { ... }



- 오버라이딩(Overriding)할 수 없는 final 메소드 : 메소드를 선언할 때 final 키워드를 붙이게 되면 이 메소드는 최종적인 메소드가 되므로 오버라이딩할 수 없는 메소드가 된다. , 부모 클래스에서 상속해서 자식 클래스를 선언할 때 부모 클래스에 선언된 final 메소드는 자식 클래스에서 재정의할 수 없다.


public final 리턴타입 메소드(매개변수) { ... } //해당 메소드 재정의 불가




* protected 접근 제한자


- 부모 클래스의 멤버가 protected 접근 제한자를 가질 경우 자식 클래스는 다른 패키지라도 부모 객체의 필드, 생성자, 메소드를 사용할 수 있다.


- 생성자의 경우, 부모 객체를 new 연산자로 생성하는 것이 아니라 자식 클래스의 생성자에서 super(); 키워드를 통해서 호출할 수 있다.

 

 

* 타입 변환과 다형성


- 다형성은 하나의 타입에 여러 객체를 대입하여 이용할 수 있는 성질을 말한다. 이러한 다형성을 위해 자바는 자식 클래스에서 부모 클래스로 자동 타입 변환하는 것을 허용한다. , 부모 타입에는 모든 자식 객체가 대입될 수 있다.

 

만약 Car 클래스를 상속하는 SportCar 클래스가 있다면,


SportCar mySportCar = new SportCar();

Car myCar = mySportCar; //자동 타입 변환


mySportCar 변수와 myCar 변수는 타입만 다를 뿐 동일한 객체(SportCar)를 참조한다.


- 매개 변수의 타입이 클래스일 경우, 해당 클래스의 객체 외에 상속받는 자식 객체까지도 매개값으로 사용할 수 있다.


- , 부모 타입으로 자동 타입 변환된 이후에는 부모 클래스에 선언된 필드와 메소드만 접근할 수 있다. , 변수는 자식 객체를 참조하더라도 해당 변수로 접근 가능한 멤버는 부모 클래스의 멤버로 제한된다.


- 그러나 메소드가 자식 클래스에서 오버라이딩 되었다면 부모 타입으로 자동 타입 변환되어도 오버라이딩된 메소드가 호출된다.


- 바로 위의 부모 클래스가 아니더라도 상속 계층에서 상위 타입이라면 하위 타입이 자동 타입변환 된다.

- 강제 타입 변환(Casting) : 자식 타입이 부모 타입으로 자동 변환한 후, 다시 자식타입으로 변환할 때 강제 타입 변환을 해야 한다. 즉, 부모 타입에 부모 객체가 아닌 자식 객체가 있는 경우에 가능하다.

 

자식클래스 변수 = (자식클래스) 부모클래스;

 

 

* 객체 타입 확인


- 강제 타입 변환은 자식 타입이 부모 타입으로 변환되어 있는 상태에서만 가능하므로 부모 타입의 변수가 부모 객체를 참조할 경우 자식 타입으로 변환할 수 없다.


- instanceof : 위의 문제점을 해결하고자 어떤 객체가 어떤 클래스의 인스턴스(객체)인지 확인하는데 사용되는 연산자이다. 


boolean result = 좌항(객체) instanceof 우항(타입);



- 해당 타입이면 true, 아니면 false를 리턴한다.


// Child extends Parent

// Child -> Parent (자동타입변환)

// Parent -> Child (캐스팅)

 

public void method(Parent parent) {

Child child1 = new Child();

Parent parent = child1;


//parent 변수가 참조하는 객체는 Child 클래스의 인스턴스(객체)인가?

if(parent instanceof Child) {

    Child child = (Child) parent

    }

}




 

+ Recent posts