내부 클래스와 내부 인터페이스에 대하여 내부 클래스의 선언 방법과 이용 방법 내부 인터페이스의 선언 방법과 이용 방법 내부 클래스와 내부 인터페이스 내부 클래스와 내부 인터페이스에 대하여 내부 클래스의 선언 방법과 이용 방법 내부 인터페이스의 선언 방법과 이용 방법
01. 내부 클래스 내부 클래스와 내부 인터페이스 내부 클래스 (nested class, 중첩 클래스) • 내부 클래스의 예 - 다음 성적표를 클래스로 표현하는 경우를 가정합시다 이렇게 표현할 수 있습니다. 하지만 이 클래스의 존재 이유가 오로지 ExamResult 클래스를 위한 것이라면?
01. 내부 클래스와 내부 인터페이스 내부 클래스와 내부 인터페이스 내부 클래스란? • 내부 클래스의 예 내부 클래스(nested class)로 선언하는 것이 좋습니다.
ExamResultTest.java 내부 클래스와 내부 인터페이스 내부 클래스 class ExamResult { String name; ItemResult[] result; class ItemResult { String subject; int points; public ItemResult(String sub, int pts) { subject = sub; points = pts; } public ExamResult() result = new ItemResult[10]; 내부 클래스
내부 클래스와 내부 인터페이스 class ExamResultTest { public static void main( String[] args ) ExamResult student1 = new ExamResult(); student1.name = "Kim"; student1.result[0] = student1.new ItemResult("Enligsh", 70); student1.result[1] = student1.new ItemResult("Math", 50); printStudent( student1 ); } public static void printStudent( ExamResult student ) ExamResult.ItemResult item; System.out.printf("----- Name: %s\n", student.name ); item = student.result[0]; System.out.printf("%s: %d\n", item.subject, item.points); item = student.result[1]; System.out.println("-------------" );
01. 내부 클래스와 내부 인터페이스 내부 클래스와 내부 인터페이스 내부 vs. 외부 • 외부 클래스(enclosing class, 둘러싼 클래스) • 내부 클래스(nested class)
내부 클래스(nested class)의 종류 내부 클래스와 내부 인터페이스 내부 클래스(nested class)의 종류 정적 내부 클래스 (static nested class) 비정적 내부 클래스 (non-static nested class = inner class) 로컬 이너 클래스 (local inner class) 익명 클래스 (anonymous inner class)
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 내부 클래스의 종류 • 정적 내부 클래스 (static nested class)
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 내부 클래스의 종류 • 이너 클래스 (inner class = non-static nested class)
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 내부 클래스의 종류 • 로컬 이너 클래스 (local inner class)
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 이너 클래스 • 다음과 같은 장바구니 데이터를 클래스로 표현하는 경우를 가정해 봅시다. 이런 데이터들은 이너 클래스로 선언하는 것이 좋습니다.
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 이너 클래스 [예제] 장바구니 클래스와 상품 항목 클래스(이너 클래스) import java.util.ArrayList; class Cart { ArrayList<Item> list = new ArrayList<Item>(); void addItem( String name, int num, int unitPrice ) list.add( new Item(name, num, unitPrice) ); } void removeItem( int index ) list.remove( index ); 이너 클래스의 생성자 호출
내부 클래스와 내부 인터페이스 이너 클래스 타입의 변수 선언 이너 클래스의 메소드 호출 이너 클래스의 필드 사용 int getNumOfItems() { return list.size(); } Item getItem( int index ) return list.get( index ); int getTotalPrice() int total = 0; for( Item item : list ) total += item.getPrice(); return total; void changeItemNumber( int index, int num ) Item item = list.get( index ); item.num = num; 이너 클래스 타입의 변수 선언 이너 클래스의 메소드 호출 이너 클래스의 필드 사용
내부 클래스와 내부 인터페이스 $ javac Cart.java $ ls class Item { String name; int num; int unitPrice; Item( String name, int num, int unitPrice ) this.name = name; this.num = num; this.unitPrice = unitPrice; } int getPrice() return num * unitPrice; 이너 클래스 $ javac Cart.java $ ls Cart$Item.class Cart.class Cart.java
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 이너 클래스의 사용 class InnerClassExample1 { public static void main( String[] args ) Cart cart = new Cart(); cart.addItem( "chocolate", 3, 1000 ); cart.addItem( "cake", 1, 25000 ); cart.addItem( "champagne", 1, 7000 ); printCart( cart ); }
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 이너 클래스의 사용 static void printCart( Cart cart ) { int numOfItems = cart.getNumOfItems(); System.out.println( "Name Num unitPrice amount" ); System.out.println( "-------------------------------------" ); for( int i = 0; i < numOfItems; i++) Cart.Item item = cart.getItem( i ); System.out.printf( "%-9s %3d %9d %6d\n", item.name, item.num, item.unitPrice, item.getPrice() ); } System.out.printf( "Total%32d\n", cart.getTotalPrice() );
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 실행결과 $ java InnerClassExample1 Name Num unitPrice amount ------------------------------------- chocolate 3 1000 3000 cake 1 25000 25000 champagne 1 7000 7000 Total 35000 $
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 이너 클래스 • 이너 클래스의 사용 방법 1) 이너 클래스 이름 앞에 인클로징 클래스 이름을 붙여야 합니다.
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 이너 클래스 • 이너 클래스의 사용 방법 2) 필드, 메소드의 사용 방법은 일반 클래스와 마찬가지입니다.
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 이너 클래스 • 인클로징 클래스의 외부에서 이너 클래스 객체를 생성하는 방법 * 인클로징 객체가 있어야 이너 클래스 객체를 만들 수 있음 인클로징 객체 이너 클래스 객체
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 main 메쏘드 수정 class InnerClassExample1 { public static void main( String[] args ) Cart cart = new Cart(); cart.addItem( "chocolate", 3, 1000 ); cart.addItem( "cake", 1, 25000 ); cart.addItem( "champagne", 1, 7000 ); Cart.Item item = cart.new Item( "flower", 1, 5000 ); cart.list.add( item); printCart( cart ); } static void printCart( Cart cart ) ···· addItem() 메쏘드를 호출하는 대신에 이너 클래스 객체를 직접 생성하여 ArrayList에 추가
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 실행결과 $ java InnerClassExample1 Name Num unitPrice amount ------------------------------------- chocolate 3 1000 3000 cake 1 25000 25000 champagne 1 7000 7000 flower 1 5000 5000 Total 40000 $
내부 클래스와 내부 인터페이스 이너 클래스 안에서 인클로징 클래스의 구성요소 사용하기 PiggyBank.java class PiggyBank { // 돼지 저금통 클래스 private int total; Slot slot; PiggyBank() { total = 0; slot = new Slot(); } int getTotal() { return total; class Slot { // 투입구 클래스 void put(int amount) { total += amount; 인클로징 클래스의 필드를 직접 사용합니다. private 멤버도 사용할 수 있음
내부 클래스와 내부 인터페이스 이너 클래스 안에서 인클로징 클래스의 구성요소 사용하기 PiggyBankTest.java class PiggyBankTest { public static void main( String[] args ) PiggyBank bank = new PiggyBank(); bank.slot.put(100); bank.slot.put(1000); System.out.println( "amount: " + bank.getTotal() ); } $ java PiggyBankTest amount: 1100
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 정적 내부 클래스 • 정적 내부 클래스(static nested class) - 필드, 메소드와 동일 수준으로 선언된 static 키워드가 붙은 내부 클래스
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 정적 내부 클래스 [예제] 직선 클래스와 점 클래스(정적 내부 클래스) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Line { // 직선 클래스 Point point1, point2; Line(int x1, int y1, int x2, int y2) { point1 = new Point(x1, y1); point2 = new Point(x2, y2); } void move(int offsetX, int offsetY) { point1.x += offsetX; point1.y += offsetY; point2.x += offsetX; point2.y += offsetY; static class Point { // 점 클래스 int x, y; Point(int x, int y) { this.x = x; this.y = y; 정적 내부 클래스의 생성자 호출 정적 내부 클래스의 필드 사용 정적 내부 클래스
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 정적 내부 클래스 • 인클로징 클래스 외부에서 정적 내부 클래스를 사용하는 방법
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 정적 내부 클래스 [예제] 직선 클래스와 점 클래스를 사용하는 프로그램 1 2 3 4 5 6 7 8 9 10 11 class LineTest { public static void main(String args[]) { Line line = new Line(0, 0, 100, 100); line.move(10, 20); printPoint(line.point1); printPoint(line.point2); } static void printPoint(Line.Point point) { System.out.printf("(%d, %d) %n", point.x, point.y); $ java LineTest (10, 20) (110, 120)
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 정적 내부 클래스 • 인클로징 클래스 외부에서 정적 내부 클래스의 객체를 생성하는 방법
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 정적 내부 클래스 [예제] 정적 내부 클래스의 객체를 생성하는 프로그램 1 2 3 4 5 6 class LineTest2 { public static void main(String args[]) { Line.Point point = new Line.Point(100, 200); System.out.printf("(%d, %d)", point.x, point.y); } 정적 내부 클래스의 객체 생성 $ java LineTest2 (100, 200)
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 정적 내부 클래스 인클로징 클래스 객체 없이 정적 내부 클래스의 객체를 생성할 수 있다. 인클로징 클래스의 private static 멤버를 사용할 수 있다.
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 인터페이스의 정적 내부 클래스 [예제] 평면 도형 인터페이스와 위치 클래스(정적 내부 클래스) 1 2 3 4 5 6 7 8 9 10 11 interface PlaneObject { // 평면 도형 인터페이스 Location getLocation(); void setLocation(int x, int y); static class Location { // 위치 클래스 int x, y; Location(int x, int y) { this.x = x; this.y = y; } 정적 내부 클래스
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 인터페이스의 정적 내부 클래스 [예제] 평면 도형 인터페이스를 구현하는 사각형 클래스 1 2 3 4 5 6 7 8 class Rectangle implements PlaneObject { // 사각형 클래스 Location location; int width, height; Rectangle(int x, int y, int width, int height) { this.location = new Location(x, y); this.width = width; this.height = height; } PlaneObject 인터페이스로부터 상속받은 정적 내부 클래스의 생성자 호출
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 인터페이스의 정적 내부 클래스 [예제] 평면 도형 인터페이스를 구현하는 사각형 클래스 9 10 11 12 13 14 15 16 public Location getLocation() { return location; } public void setLocation(int x, int y) { location.x = x; location.y = y; 정적 내부 클래스의 필드 사용
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 인터페이스의 정적 내부 클래스 [예제] 평면 도형 인터페이스를 구현하는 사각형 클래스 1 2 3 4 5 6 7 8 9 10 11 class RectangleTest { public static void main( String[] args ) Rectangle rect = new Rectangle( 0, 0, 100, 200 ); rect.setLocation( 50, 50 ); Rectangle.Location loc = rect.getLocation(); System.out.printf( "(%d, %d)\n", loc.x, loc.y ); }
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 로컬 이너 클래스 • 로컬 이너 클래스(local inner class) 메소드 본체 안에 선언된 내부 클래스 메소드 내에서 임시로 사용하는 클래스
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 로컬 이너 클래스 [예제] 연락처 프로그램과 연락처 클래스 class ContactInfo { String name; String phone; ContactInfo( String name, String phone ) { this.name = name; this.phone = phone; } 이런 클래스들이 있다고 가정합시다. import java.util.HashMap; class ContactInfoTest { public static void main( String[] args ) { HashMap< String, ContactInfo > table = new HashMap< String, ContactInfo >(); table.put( "Kim", new ContactInfo("Kim", "02-547-0000") ); table.put( "Han", new ContactInfo("Han", "010-9574-0280") ); ContactInfo obj = table.get( "Kim" ); System.out.printf( "%s: %s\n", obj.name, obj.phone ); } 이 클래스가 오로지 왼쪽 클래스의 main 메소드 내에서만 필요하다면?
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 로컬 이너 클래스 import java.util.HashMap; class LocalClassExample { public static void main( String[] args ) { class ContactInfo { String name; String phone; ContactInfo( String name, String phone ) { this.name = name; this.phone = phone; } HashMap< String, ContactInfo > table = new HashMap< String, ContactInfo >(); table.put( "Kim", new ContactInfo("Kim", "02-547-0000") ); table.put( "Han", new ContactInfo("Han", "010-9574-0280") ); ContactInfo obj = table.get( "Kim" ); System.out.printf( "%s: %s\n", obj.name, obj.phone ); 로컬 이너 클래스
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 로컬 이너 클래스 [예제] 메시지 송신 클래스와 서브클래스들 abstract class MessageSender { String sender, receiver; MessageSender( String sender, String receiver ) { this.sender = sender; this.receiver = receiver; } abstract void send( String message );
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 로컬 이너 클래스 [예제] 메시지 송신 클래스와 서브클래스들 class EMailSender extends MessageSender { EMailSender( String sender, String receiver ) { super( sender, receiver ); } void send( String message ) { System.out.println( “Sender:" + sender ); System.out.println( “Receiver:" + receiver ); System.out.println( “Contents:" + message ); System.out.println();
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 로컬 이너 클래스 [예제] 메시지 송신 클래스와 서브클래스들 class SMSSender extends MessageSender { SMSSender( String callbackNo, String phoneNo ) { super( callbackNo, phoneNo ); } void send( String message ) { System.out.println( "Phone Number: " + receiver ); System.out.println( "Contents: " + message ); System.out.println( "callback Number: " + sender ); System.out.println();
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 로컬 이너 클래스 [예제] 메시지 송신 클래스와 서브클래스들 class SenderTest { public static void main( String[] args ) { EMailSender email = new EMailSender( "schan@naver.com", "mkpark@naver.com" ); email.send( "Hi, this is an email" ); SMSSender sms = new SMSSender( "010-000-0000", "010-111-1111" ); sms.send( "Hi, this is a SMS" ); } $ java SenderTest Sender: schan@naver.com Receiver: mkpark@naver.com Contents: Hi, this is an email Phone Number: 010-000-0000 Contents: Hi, this is a SMS callback Number: 010-111-1111
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 로컬 이너 클래스 • 다음과 같은 클래스가 추가로 필요하다면? class KatokSender extends MessageSender { KatokSender( String senderID, String receiverID ) { super( senderID, receiverID ); } void send( String message ) { System.out.println( "Sender ID: " + sender ); System.out.println( "Receiver ID: " + receiver ); System.out.println( "Contents: " + message ); System.out.println(); 그리고 이 클래스가 특정 프로그램의 특정 메소드 내에서만 필요하다면?
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 [예제] 다른 클래스를 상속 받는 로컬 이너 클래스의 예 class UsingLocalClass { public static void main( String[] args ) { class KatokSender extends MessageSender { KatokSender( String senderID, String receiverID ) { super( senderID, receiverID ); } void send( String message ) { System.out.println( "Sender ID: " + sender ); System.out.println( "Receiver ID: " + receiver ); System.out.println( "Contents: " + message ); System.out.println(); KatokSender talk = new KatokSender( "S.Han", "M.Park" ); talk.send( "This message is sent using local inner class" );
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 • 앞 프로그램은 다음과 같은 방법으로 더 간단하게 만들 수 있습니다. public static void main( String[] args ) { class KatokSender extends MessageSender { MessageSender talk = new MessageSender( “S.Han”, “M.Park” ) { void send( String message ) { System.out.println( "Sender ID: " + sender ); System.out.println( "Receiver ID: " + receiver ); System.out.println( "Contents: " + message ); System.out.println(); } }; KatokSender talk = new KatokSender( "S.Han", "M.Park" ); talk.send( "This message is sent using local inner class" ); 상위클래스 생성자 호출 상위클래스 변수 선언 클래스 본체는 그대로 이런 이너 클래스를 익명 클래스(anonymous inner class)라고 부릅니다.
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 익명 클래스 (anonymous inner class) class UsingAnonymousClass { public static void main( String[] args ) { MessageSender talk = new MessageSender( "S.Han", "M.Park" ) { void send( String message ) { System.out.println( "Sender ID: " + sender ); System.out.println( "Receiver ID: " + receiver ); System.out.println( "Contents: " + message ); System.out.println(); } }; talk.send( "This message is sent using anonymous class" ); 익명 클래스의 선언 및 객체 생성 익명 클래스 객체의 메소드 호출
02. 내부 클래스의 선언과 이용 내부 클래스와 내부 인터페이스 익명 클래스(인터페이스를 구현한 클래스) interface Player { void play(String source); void stop(); } class UsingAnonymousClass2 { public static void main(String args[]) { Player obj = new Player() { public void play(String source) { System.out.println(“Start playing: ” + source); } public void stop() { System.out.println(“Stop playing”); }; obj.play(“What_is_love.mp3"); obj.stop(); Player 인터페이스를 구현하는 익명 클래스 선언 및 객체생성 익명 클래스 객체의 메소드 호출
내부 클래스와 내부 인터페이스 03. 내부 인터페이스의 선언과 이용 내부 인터페이스의 종류 • 정적 내부 인터페이스 (1)
02. 내부 인터페이스의 선언과 이용 내부 클래스와 내부 인터페이스 내부 인터페이스의 종류 • 정적 내부 인터페이스 (2) 내부 인터페이스는 정적 내부 인터페이스 한 종류만 있습니다.
상속받은 내부 인터페이스를 구현하는 내부 클래스 내부 클래스와 내부 인터페이스 03. 내부 인터페이스의 선언과 이용 내부 인터페이스 abstract class PlayerFactory { abstract Player createPlayer(); interface Player { void play(String source); void stop(); } 내부 인터페이스 class MP3PlayerFactory extends PlayerFactory { public Player createPlayer() { return new MP3Player(); } class MP3Player implements Player { public void play(String source) { System.out.println(“Start playing: " + source); public void stop() { System.out.println(“Stop playing"); 상속받은 내부 인터페이스를 구현하는 내부 클래스
03. 내부 인터페이스의 선언과 이용 내부 클래스와 내부 인터페이스 내부 인터페이스 [예제] MP3PlayerFactory 클래스를 사용하는 프로그램 class MP3PlayerFactoryTest { public static void main( String args[] ) { MP3PlayerFactory factory = new MP3PlayerFactory(); PlayerFactory.Player player = factory.createPlayer(); player.play( “What_is_love.mp3“ ); player.stop(); }