기록공간

클래스 고급 - 인터페이스(Interface) 본문

Java

클래스 고급 - 인터페이스(Interface)

입코딩 2020. 8. 25. 22:26
반응형

인터페이스(Interface) 란?

인터페이스는 클래스를 위한 템플릿으로써의 기능을 수행하는 추상 클래스의 한 종류이다. 완전히 미완성된 채로 남겨져 인터페이스 안에 존재하는 그 어떤 메소드도 몸체(정의부, 구현부) 가 없기 때문에 사실상 실행 부분이 존재하지 않는다. 

 

인터페이스는 클래스와 다르게 다중 상속이 가능하며 인터페이스 자체도 상속된다. 기존의 C++ 언어 등에서 지원되는 다중 상속이 사용 과정에서 많은 문제점을 노출시켰기 때문에 자바에서는 다중 상속의 개념을 인터페이스라는 개념으로 변형하여 인터페이스를 통해 다중 상속을 구현하는 방법을 지원한다.

 

인터페이스는 상수추상 메소드만 가질 수 있으며 인터페이스 안의 메소드들은 접근제어 지시자를 명시하지 않아도 public으로 설정되어 클래스의 구현(implement) 함으로써 바로 접근이 이루어 질 수 있다.

 

특징

  • 추상 클래스의 일종으로 선언만 있고 정의가 없다.

  • final 변수는 가질 수 있다. (상수)

  • public static final 상수만 만들 수 있다.

  • 인터페이스를 구현하기 위해서는 extends 대신 implements를 사용한다.

  • 하나 이상의 인터페이스를 implements 할 수 있다.

  • 인터페이스를 implements 한 클래스는 인터페이스의 모든 메소드를 오버라이딩 해야 한다. 모든 메소드가 오버라이딩 되어 있지 않는다면 상속받은 클래스는 추상 클래스로 선언해야 한다.

  • 인터페이스가 다른 인터페이스를 상속받을 수 있으며 이 때, extends 키워드를 사용한다. 또한, 클래스와 달리 다중 상속이 가능하다.

implements

인터페이스는 클래스를 위한 템플릿이기 때문에 사용 가능한 인터페이스가 되기 위해서는 자바 프로그램에서 인터페이스를 구현해 줘야 하는데 이러한 기능을 하는 것이 implements 예약어이다. 인터페이스 특성상 클래스는 동시에 두 개 이상의 인터페이스를 implements 할 수 있다.

 

예제 1)

// 인터페이스
interface Demo
{
	public static final double PI = 3.141592;

	// 인터페이스의 멤버 변수는
	// [static final]을 별도로 명시하지 않아도
	// 자동으로 [static final]인 상태~!!!
	public int a = 10;

	// 인터페이스의 메소드는 선언만 가능(정의, 구현 불가)
	// 자동으로 [abstract] 인 상태~!!!
	//public abstract void print();
	public void print();
	/*
	public void print()
	{
		System.out.println("PI : " + PI);
	}
	*/
}

// 클래스
// class DemoImpl
// class DemoImpl extends Demo
// class DemoImpl implements Demo
//    
// 추상 클래스 - 인터페이스를 구현하는 추상 클래스
//abstract class DemoImpl implements Demo

// 클래스 - 인터페이스를 구현하는 클래스
class DemoImpl implements Demo
{
	@Override
	public void print()
	{
		System.out.println("인터페이스 메소드 재정의...");
	}

	public void write()
	{
		System.out.println("클래스에 정의된 메소드...");
	}
}

// 클래스 - main() 메소드를 포함하고 있는 외부 클래스(동일 패키지)
public class Test122
{
	public static void main(String[] args)
	{
		//Demo ob = new Demo();		//-- 생성 불가~!!!
		//-- 인터페이스를 가지고 인스턴스 생성을 하는 것은 불가능하다.

		//DemoImpl ob = new DemoImpl();
		//-- Demo 소유의 printf() 메소드 재정의 후 가능~!!!

		//DemoImpl obTemp = new DemoImpl();
		//Demo ob = (Demo)obTemp;
		//Demo ob = obTemp;

		// ○ 업 캐스팅
		// 인터페이스 객체는 상위 객체
		Demo ob = new DemoImpl();
		ob.print();
		// --==>> 인터페이스 메소드 재정의...

		//ob.write();
		//--==>> 에러 발생(컴파일 에러)
		
		// ○ 다운 캐스팅
		((DemoImpl)ob).write();
		// --==>> 클래스에 정의된 메소드...


		System.out.println(Demo.PI);		// -- static 이기 때문에 가능하다.
		// --==>> 3.141592

		System.out.println(Demo.a);		// -- static 이기 때문에 가능하다.
		// --==>> 10
		
		//Demo.a = 30;				// -- final 이기 때문에 (상수이기 때문에) 가능하다.
		// --==>> 에러 발생


	}
}

 

예제2) - 다중상속 상황

// 인터페이스
interface ADemo
{
	public void write();
	//public abstract void write();
}

// 인터페이스
interface BDemo
{
	public void print();
	//public abstract void print();
}

// ※ 인터페이스는 2개 이상을 구현(implements)할 수 있다.
//	   -> 클래스가 다중 상속이 되지 않는 부분을 보완(보충)하는 개념

// 클래스
//class DemoImpl 
//class DemoImpl extends ADemo, BDemo
// 추상 클래스 - 두 인터페이스를 구현한 추상 클래스
//abstract class DemoImpl implements ADemo, BDemo
class DemoImpl implements ADemo, BDemo
{
	/*
	public void write();
	public void print();
	*/

	// JDK 1.5(5.0)에서는 인터페이스 메소드를
	// 오버라이딩(Overriding)할 때
	// [@Override] 어노테이션(annotation)을 사용할 수 없다.
	// JDK 1.6(6.0) 이후부터 적용 가능한 문법이다.
	// 단, 상속받은 클래스의 메소드를 오버라이딩(Overriding)할 떄에는
	// JDK 1.5(5.0)에서도 [@Override] 어노테이션(annotation) 사용이 가능하다.
	@Override
	public void write()
	{
		System.out.println("ADemo 인터페이스 메소드 write() ... ");
	}

	@Override
	public void print()
	{
		System.out.println("BDemo 인터페이스 메소드 print() ... ");
	}
}

// 클래스 - main() 메소드를 포함하는 외부의 다른 클래스(동일 패키지)
public class Test123
{
	public static void main(String[] args)
	{
		//ADemo ob = new ADemo();	//-- 인터페이스 -> 인스턴스 생성 불가
		//BDemo ob = new BDemo();	//-- 인터페이스 -> 인스턴스 생성 불가

		// ADemo, BDemo 인터페이스를 구현(implements)한 클래스
		// (-> DemoImpl)
		// 기반의 인스턴스 생성
		DemoImpl ob1 = new DemoImpl();

		ob1.write();
		ob1.print();
		//--==>> ADemo 인터페이스 메소드 write() ...
		//	     BDemo 인터페이스 메소드 print() ...

		ADemo ob2 = new DemoImpl();			//-- 업 캐스팅
		BDemo ob3 = new DemoImpl();			//-- 업 캐스팅

		//ob2.print();	// --==>> 에러 발생
		//ob3.write();	// --==>> 에러 발생

		ob3.print();
		ob2.write();
		//	--==>>	BDemo 인터페이스 메소드 print() ...
		//			ADemo 인터페이스 메소드 write() ...

		((BDemo)ob2).print();
		((ADemo)ob3).write();
		// --	DemoImpl 클래스가 두 인터페이스를 모두 구현했기 때문에 가능하다.
		//		만약 DemoImpl 클래스가 이들 중 한 인터페이스만 구현했다면
		//		이 구문은 런타임 에러 발생하는 구문이다.
		// --==>> BDemo 인터페이스 메소드 print() ...
		//        ADemo 인터페이스 메소드 write() ...
		
		// ○ 다운 캐스팅
		((DemoImpl)ob3).write();
		// --==>> ADemo 인터페이스 메소드 write() ...
	}
}

 

예제3) - 인터페이스를 사용해 추상클래스에 implement

// 인터페이스
interface Demo
{
	public void write();
	public void print();
}

// 클래스 - 인터페이스를 구현하는 추상 클래스
//class DemoImpl implements Demo
//
abstract class DemoImpl implements Demo
{
	@Override
	public void write()
	{
		System.out.println("write() 메소드 재정의 ... ");
	}

	// public void print();
}

// 클래스
//class DemoImplSub extends DemoImpl
// 추상 클래스를 상속받는 추상 클래스
//abstract class DemoImplSub extends DemoImpl
// 추상 클래스를 상속받는 클래스
class DemoImplSub extends DemoImpl
{
	@Override
	public void print()
	{
		System.out.println("print() 메소드 재정의 ... " );
	}
}

// 클래스 - main() 메소드를 포함하고 있는 외부의 다른 클래스(동일 패키지)
public class Test124
{
	public static void main(String[] args)
	{
		//Demo ob1 = new demo();
		// -- 인터페이스 -> 인스턴스 생성 불가
		//DemoImpl ob2 = new DemoImpl();
		// -- 추상클래스 -> 인스턴스 생성 불가

		DemoImplSub ob3 = new DemoImplSub();

		ob3.write();
		ob3.print();
	}
}

 

예제4) - extends를 이용해 여러 인터페이스 다중 상속

// 인터페이스
interface ADemo
{
	public void write();
}

// 인터페이스
interface BDemo
{
	public void print();
}

// ※ 클래스는 다중 상속을 지원하지 않지만,
//	  인터페이스는 다중 상속을 지원한다.

// 인터페이스 - 두 인터페이스(ADemo, BDemo)를 상속받은 인터페이스
interface CDemo extends ADemo, BDemo
{
	public void test();
	
	//public void write();
	//public void print();
}

// 클래스
//class DemoImpl
// 두 인터페이스(ADemo, BDemo)를 상속받은 인터페이스(CDemo)를 구현한 추상 클래스
//abstract class DemoImpl implements CDemo
// 두 인터페이스(ADemo, BDemo)를 상속받은 인터페이스(CDemo)를 구현한 후
// 모든 메소드를 재정의한 클래스
class DemoImpl implements CDemo
{
	@Override
	public void test()
	{
		System.out.println("test()...");
	}

	@Override
	public void write()
	{
		System.out.println("write()...");
	}

	@Override
	public void print()
	{
		System.out.println("print()...");
	}
	
}

// 클래스
public class Test125
{
	public static void main(String[] args)
	{
		// 두 인터페이스를 상속받은 인터페이스를 구현하고
		// 모든 메소드를 재정의한 클래스에 대한 인스턴스 생성
		DemoImpl ob = new DemoImpl();

		ob.test();
		ob.write();
		ob.print();
	}
}
반응형

'Java' 카테고리의 다른 글

Java의 주요 클래스(2)  (0) 2020.08.27
Java의 주요 클래스(1)  (0) 2020.08.26
클래스 고급 - 중첩 클래스(내부 클래스)  (0) 2020.08.25
클래스 고급 - 클래스 캐스팅  (0) 2020.08.25
클래스 고급 - 상속과 다형성  (0) 2020.08.25
Comments