티스토리 뷰

추상 (Abstract) 클래스

추상 클래스는 미완성된 클래스를 뜻하며, 선언되어 있지만 구현되지 않은 미완성의 메소드(추상 메소드)를 포함하고 있는 클래스일 때 반드시 abstract 키워드를 class 앞에 붙여준다.

클래스로서의 객체 생성은 못 하지만 새로운 클래스를 작성할 때 부모 클래스로 이용되며 새 클래스 작성을 위한 템플릿이 되어 상속받은 클래스들의 규칙을 주는 용도로 사용 가능하다.

public abstract class 클래스이름 {
	// 필드, 생성자, 메소드 작성
    	// 미완성된 추상 메소드 선언
}

클래스 앞에 'abstract' 키워드를 붙이면 추상 클래스가 생성되며, 객체를 생성할 수 없다는 점만 빼면 일반 클래스와 다른 점이 없다.

 

추상 (abstract) 메소드

메소드는 접근제어자, 리턴타입, 이름, 매개변수로 이루어진 선언부와 메소드의 기능을 정의하는 구현부로 나눈다. 추상 메소드는 구현부 ( '{ }' Body ) 를 가지지 않는다!!

접근제한자 abstract 리턴타입 함수이름();

추상 클래스에서 추상 메소드를 제공하는 이유는, 추상 클래스를 상속받아 만들어지는 후손 클래스들이 메소드를 처음 선언과 동일하게 재정의해서 사용하라는 의미이다. 반드시 구현부를 작성해야 하므로 강제성도 가지고 있다.

 

다음 코드를 통해 Abstract class 의 예를 살펴보겠다.

 

Abstract class 1.

package com.test01;

/*
 * 추상 클래스 : 추상 메서드를 하나 이상 가진 클래스
 */
public abstract class Animal {

	// 추상 메서드 : 상속받는 자식 class 에서 반드시 구현하도록 강제!
	// body { } 가 없다.
	public abstract void bark();

	public void eat(String feed) {
		System.out.println(feed + " 먹는다.");
	}

}
package com.test01;

public class Dog extends Animal {

	// 추상클래스 Animal 을 상속받은 cat 은 추상클래스의 추상 메서드를 반드시 구현해야한다.
	@Override
	public void bark() {
		System.out.println("멍멍~!");

	}
	
	public void eat(String feed) {
		System.out.println("멍멍이가 " + feed + " 먹는다.");
	}

}
package com.test01;

public class Cat extends Animal {

	// 추상클래스 Animal 을 상속받은 cat 은 추상클래스의 추상 메서드를 반드시 구현해야한다.
	@Override
	public void bark() {
		System.out.println("야옹~!");
	}

	public void eat(String feed) {
		if (feed.equals("츄르츄르")) {
			System.out.println("고양이가 " + feed + " 를 격하게 먹는다.");
		} else {
			System.out.println("고양이가 " + feed + " 먹는다.");
		}
	}
}

main()

package com.test01;

public class MTest {

	public static void main(String[] args) {
		Animal cat = new Cat();
		Animal dog = new Dog();
		
		cat.bark();
		dog.bark();
		cat.eat("츄르츄르");
		dog.eat("생닭");
		
		// 추상클래스는 객체 생성 불가!!!!!******
		// Animal some = new Animal();
		
		/*
		 * 반드시 무언가를 구현해야만 할 때 주로 추상 클래스를 사용
		 */
	}
}

Abstract class 2. ( + 동적 바인딩 )

package com.test02;

public abstract class Animal {

	public abstract void start();

	public abstract void stop();

}
package com.test02;

public class Dog extends Animal {

	@Override
	public void start() {
		System.out.println("멍멍이 걷는다.");

	}

	@Override
	public void stop() {
		System.out.println("멍멍이 걷는다.");

	}

}
package com.test02;

public class Cat extends Animal {

	@Override
	public void start() {
		System.out.println("고양이 걷는다.");

	}

	@Override
	public void stop() {
		System.out.println("고양이 멈췄다.");

	}

}
package com.test02;

public class Panda extends Animal {

	@Override
	public void start() {
		System.out.println("판다 걷는다.");

	}

	@Override
	public void stop() {
		System.out.println("판다 걷는다.");

	}

}

main()

package com.test02;

import java.util.Scanner;

public class MTest {

	/*
	 * 동적 바인딩 : 런타임 시 메모리 할당을 하면서 메모리를 동적으로 연결하는 방식
	 * 
	 * why? 1. 메모리 절약 2. 실행속도 향상 3. 행위 은닉
	 */

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("선택해 주세요 [1:고양이 2:멍멍이 3:렛서팬더]");
		int select = sc.nextInt();

		// Animal 타입 변수에
		Animal some = null;

		// 동적 바인딩 : 사용자의 선택에 따라 객체가 선택됨!
		switch (select) {
		case 1:
			some = new Cat();
			break;
		case 2:
			some = new Dog();
			break;
		case 3:
			some = new Panda();
			break;

		}
		some.start();
		some.stop();

	}
}

 

 

 

 

 

 

인터페이스 (Interface)

추상 메소드로만 구성된 추상클래스를 인터페이스(interface) 라고 구분하였으며, 추상 클래스보다 추상화 정도를 높여 일반 메소드와 멤버변수를 멤버로 가질 수 없게 하였다.

추가로 상수(public static final 필드) 만 멤버로 가진다.

인터페이스는 다중 상속에 제한이 없기 때문에 여러 추상화 메소드를 인터페이스로 작성함으로써 코드의 강제성을 부여할 수 있고, 여러 클래스에서 사용되는 동일한 상수일 경우 인터페이스에 정의한 후 해당 상수를 공유할 수 있게 하면 중복을 줄일 수 있다.

 

인터페이스 작성

추상 메소드를 작성하려면 abstract 키워드를 표시해야 하지만 인터페이스 내부에는 모든 메소드가 추상 메소드이므로 public abstract 키워드를 생략할 수 있다. 하지만 혼동할 수 있으므로 모든 인터페이스의 추상 메소드에 public abstract 를 표시해 두기도 한다.

public interface 인터페이스이름 {
	// 상수 또는 추상 메소드
}

 

인터페이스 상속

클래스의 상속은 단일 상속만 가능하지만, 인터페이스는 다중 상속이 가능하다.

public interface 인터페이스 extends 인터페이스1, 인터페이스2, ... {
	// 상수 또는 추상 메소드
}

추상 메소드에 대한 구현 (implement) 과 재정의 (Overriding) 는 인터페이스를 상속받은 후손 클래스에서 구현(implement) 해야 한다.

 

인터페이스 구현 (implement)

인터페이스가 가진 추상 메소드를 구현하려면 'implements' 키워드를 사용해서 후콘 클래스가 인터페이스를 상속받아야 한다. 상속받은 후손 클래스는 반드시 인터페이스의 추상 메소드를 구현(implement : 메소드 바디 추가하고 코드를 작성) 해야만 한다.

public class 클래스이름 implements 인터페이스 {
	// 일반 클래스 정의
    	//인터페이스 추상 메소드 구현
}

 

인터페이스 장점

인터페이스를 이용하면 정의해야 하는 메소드(프로그램기능)를 표준화하고 강제화할 수 있다. 또한 메소드화 시켜야 하는 기능을 분류해야 하는 고민없이 구현만 하면 되므로 개발시간을 단축시킬 수 있다. 일반 클래스 상속을 이용해서 자식 클래스들의 관계를 맺는 것보다 간편하게 관계를 맺을 수 있다.

 

다음 코드를 통해 Interface 의 예를 살펴보겠다.

 

interface 1.

package com.test03;

/*
 * interface : 모든 메서드가 추상메서드 이다!
 *
 * class -> class : extends
 * class -> interface : implements
 * interface -> interface : extends
 */
public interface Animal {

	public void bark();
	void eat(String feed);
}
package com.test03;

public class Dog implements Animal {

	@Override
	public void bark() {
		// TODO Auto-generated method stub
		System.out.println("멍멍");
	}

	@Override
	public void eat(String feed) {
		// TODO Auto-generated method stub
		System.out.println("멍멍이가 " + feed + " 먹는다.");
	}

}
package com.test03;

public class Cat implements Animal {

	@Override
	public void bark() {
		// TODO Auto-generated method stub
		System.out.println("야옹");
	}

	@Override
	public void eat(String feed) {
		// TODO Auto-generated method stub
		System.out.println("고양이가 " + feed + " 먹는다.");
	}

}

main()

package com.test03;

public class MTest {

	public static void main(String[] args) {
		Animal cat = new Cat();
		cat.bark();
		cat.eat("츄르츄르");
		
		Animal dog = new Dog();
		dog.bark();
		dog.eat("사료");
	}
}

 

interface 2.

 

package com.tv;

public interface TV {

	int volumeUp();
	int volumeDown();
	
	/*
	 * TV를 상속받는 SamsungTV 와 LgTV 를 만들자.
	 * SamsungTV 는 volumeUp/Down 시 크기가 +-2 씩
	 * LgTV 는 volumeUp/Down 시 크기가 +-3 씩 증감한다.
	 * 
	 * SamsungTV와 LgTV에서 volume 이라는 field 를 만들고,
	 * 위의 기능을 하도록 코드를 작성하자.
	 * (getter & setter 도 생성)
	 */
}
package com.tv;

public class SamsungTV implements TV {

	private int volume;
	
	public SamsungTV() {
		this.volume = 0;
	}
	
	@Override
	public int volumeUp() {
		// TODO Auto-generated method stub
		this.volume += 2;
		return this.volume;
	}

	@Override
	public int volumeDown() {
		// TODO Auto-generated method stub
		this.volume -= 2;
		return this.volume;
	}

	public int getVolume() {
		return volume;
	}

	public void setVolume(int volume) {
		this.volume = volume;
	}

}
package com.tv;

public class LgTV implements TV {
	
	private int volume;

	public LgTV() {
		this.volume = 0;
	}
	@Override
	public int volumeUp() {
		// TODO Auto-generated method stub
		this.volume += 3;
		return this.volume;
	}

	@Override
	public int volumeDown() {
		// TODO Auto-generated method stub
		this.volume -= 3;
		return this.volume;
	}

	public int getVolume() {
		return volume;
	}

	public void setVolume(int volume) {
		this.volume = volume;
	}

}

main()

package com.tv;

public class MTest {

	public static void main(String[] args) {
		SamsungTV samsung = new SamsungTV();
		samsung.volumeUp();
		samsung.volumeDown();
		System.out.println(samsung.getVolume());
		
		LgTV lg = new LgTV();
		lg.volumeUp();
		lg.volumeUp();
		lg.volumeDown();
		System.out.println(lg.getVolume());
	}
}

 

 

Abstract class + Interface

 

다음 코드를 통해 Abstract class 와 Interface 를 동시에 사용하는 예를 살펴보겠다.

 

abstract class + interface 1.

package com.test04;

public abstract class Animal {

	public abstract void bark();

	public void eat(String feed) {
		System.out.println(feed + " 먹는다.");
	}
}
package com.test04;

public interface Bird {
	public void fly();
}
package com.test04;

public class Dog extends Animal {

	@Override
	public void bark() {
		// TODO Auto-generated method stub
		System.out.println("멍멍");
	}

	public void eat(String feed) {
		System.out.println("멍멍이가 " + feed + " 먹는다.");
	}

	public void bite() {
		System.out.println("멍멍이가 물었다.");
	}
}
package com.test04;

public class Cat extends Animal {

	@Override
	public void bark() {
		// TODO Auto-generated method stub
		System.out.println("야옹");
	}

	public void eat(String feed) {
		System.out.println("고양이가 " + feed + " 먹는다.");
	}

}
package com.test04;

public class Eagle extends Animal implements Bird {

	@Override
	public void fly() {
		// TODO Auto-generated method stub
		System.out.println("파닥파닥");
	}

	@Override
	public void bark() {
		// TODO Auto-generated method stub
		System.out.println("끼요오오오,,,");
	}

}

main()

package com.test04;

public class MTest {

	public static void main(String[] args) {

		Animal some = new Cat();
		some.bark();
		some.eat("참치");
		
		Dog dog = new Dog();
		dog.bark();
		dog.eat("뼈다귀");
		dog.bite();
		
		Eagle eagle = new Eagle();
		eagle.bark();
		eagle.eat("쥐");
		eagle.fly();
	}
}

 

abstract class + interface 2.

package com.profile;

public class Profile {

	private String name;
	private String phone;

	public Profile(String name, String phone) {
		this.name = name;
		this.phone = phone;
	}

	public void prn() {
		System.out.println("이    름 : " + name);
		System.out.println("전화번호 : " + phone);
	}
}
package com.profile;

public interface Job {

	public String JOB_ID = "IT";
	public void jobLoc(String loc);
}
package com.profile;

public interface Display {

	public void display();
}
package com.profile;

public class MyProfile extends Profile implements Job, Display {

	private String loc;
	
	public MyProfile(String name, String phone) {
		// TODO Auto-generated constructor stub
		super(name, phone);
	}

	@Override
	public void display() {
		// TODO Auto-generated method stub
		super.prn();
		System.out.println("회사주소 : " + loc);
		System.out.println("회사직종 : " + JOB_ID);	
		//super.JOB_ID -> X : 부모 클래스만 super가능, JOB_ID 를 가지고 있는 Job 은 interface 이다.
	}

	@Override
	public void jobLoc(String loc) {
		// TODO Auto-generated method stub
		this.loc = loc;
	}

}

main()

package com.profile;

public class MTest {

	/*
	 * Profile 과 Display, Job 을 상속받는
	 * MyProfile 클래스를 만들자. 
	 */
	public static void main(String[] args) {
		MyProfile my = new MyProfile("kh", "010-1234-5678");
		my.jobLoc("강남");
		my.display();
	}
}

 

Abstract class + Interface 3.

package com.area;

public interface Area {

	String PRINT = "넓이 : ";
	
	public void print();
	public void make();
}
package com.area;

public abstract class AreaImpl implements Area {

	private String result;
		
	public void setResult(String result) {
		this.result = result;
	}

	@Override
	public void print() {
		// TODO Auto-generated method stub
		System.out.println(PRINT + result);
	}

	@Override
	public abstract void make();

}
package com.area;

import java.util.Scanner;

public class Triangle extends AreaImpl {

	@Override
	public void make() {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		System.out.println("밑변의 길이를 입력해 주세요 : ");
		System.out.println("높이를 입력해 주세요 : ");

		int x = sc.nextInt();
		int y = sc.nextInt();
		super.setResult(Double.toString((double)(x * y) / 2));
	}

	public void print() {
		System.out.print("삼각형의 ");
		super.print();
	}
}
package com.area;

import java.util.Scanner;

public class Circle extends AreaImpl {

	@Override
	public void make() {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		System.out.println("반지름을 입력해 주세요 : ");

		double r = sc.nextDouble();
		super.setResult(Double.toString(r * r * Math.PI));

	}

	public void print() {
		System.out.print("원의 ");
		super.print();
	}
}
package com.area;

import java.util.Scanner;

public class Square extends AreaImpl {

	@Override
	public void make() {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		System.out.println("밑변의 길이을 입력해 주세요 : ");
		System.out.println("높이를 입력해 주세요 : ");

		int x = sc.nextInt();
		int y = sc.nextInt();
		super.setResult(Double.toString((double)(x * y)));
	}

	public void print() {
		System.out.print("사각형의 ");
		super.print();
	}
}

main()

package com.area;

import java.util.Scanner;

public class MTest {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		System.out.println("도형을 선택해 주세요 : ");
		System.out.println("[1:원 2:삼각형 3:사각형]");
		
		int select = sc.nextInt();
		Area ar = null;
		
		switch(select) {
		case 1:
			ar = new Circle();
			break;
		case 2:
			ar = new Triangle();
			break;
		case 3:
			ar = new Square();
			break;
		}
		
		ar.make();
		ar.print();
	}
	
}





공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
글 보관함