Java 정리 15
03 Dec 2018
Reading time ~4 minutes
Java 정리 15 - 객체다형성, abstract class, interface
객체다형성
- 같은 이름의 객체를 다르게 쓸 수 있는 것
-
is-a 관계 객체화
-
부모클래스로 데이터형 선언, 자식클래스 생성자로 객체화 하는 것
- 자식은 부모를 알고 있기 때문에 가능
- 부모만 사용할 수 있으면 됨.
-
부모클래스의 자원(변수, 메소드) 사용 가능, 자식클래스 자원 사용 불가
- 단, 자식이 Override한 method는 사용가능
-
부모클래스로 데이터형 선언, 자식클래스 생성자로 객체화 하는 것
부모클래스명 객체명 = new 자식클래스생성자();
class Super{
int i;
public Super() { }
public void printI() { System.out.println("부모 i="+i); }
}
class Sub extends Super {
int i;
int j;
@Override
public void printI() { System.out.println("자식 i="+i+", 부모 i="+super.i); }
public void printJ() { System.out.println("자식 j="+j); }
}
class IsARelation {
public static void main(String[] args) {
// s로 부모클래스의 변수, 메소드, 자신의 자원 사용가능
Sub s = new Sub();
s.i = 10;
s.printI(); // 자식 i=10, 부모 i=0
// 부모클래스의 변수, 메소드, Override된 자식메소드 사용가능
Super s2 = new Sub();
s2.i = 100;
s2.printI(); // 자식 i=0, 부모 i=100
}
}
추상클래스
- 클래스는 명사적특징을 정의한 변수, 동사적 특징(일)을 정의한 메소드가 존재
- 메소드는 부모가 구현하는 경우와 부모가 구현하지 않는 경우로 구분됨
- 부모가 구현하지 않는 경우 사용하는게 추상 메소드
- 추상클래스는 상속을 목적으로 만들어지는 클래스
- abstract method를 가질 수 있는 class
- 자식클래스가 반드시 구현하도록 강제성을 부여
-
객체화가 되지 않음
- 자식 클래스가 생성되면서 부모가 만들어지는 경우에는 객체화가 된다
-
추상메소드
- method의 body가 없다.
- 일을 정의할 수 없고 일의 목록만 정의
- 자식클래스에서 반드시 구현해야 함
// abstract class
접근지정자 abstract class 클래스명 { ... }
// abstract method
접근지정자 abstract 반환형 method명(매개변수명, ...);
/* 접근 지정자
다른 패키지에서 상속받아 사용해서 보통 public, protected 사용
public
protected
default
static
synchronized
---------------------------------------------------------
final - 상속(Override)을 막기 때문에 final 사용불가
*/
/**
* 상속을 목적으로 만드는 부모클래스
* 객체화가 안됨
* 자식클래스가 반드시 구현해야할 abstract method를 가지는 클래스.
*/
abstract class AbstractSuper {
int i;
public AbstractSuper() {
// 자식클래스가 생성될때만 호출됨
System.out.println("AbstractSuper의 생성자");
}
public void method() {
System.out.println("부모 일반 method");
}
// abstract method는 자식이 반드시 구현해야할 일의 목록을 정의
public abstract void absMethod();
public abstract String absMethod1(int i);
/* public static void main(String[] args) {
new AbstractSuper(); // 추상클래스는 객체화 될 수 없다.
} */
}
/**
* 추상클래스를 부모로 하는 자식클래스
* 자식클래스는 반드시 부모클래스의 모든 추상 메소드를 Override 해야한다.
*/
class AbstractSub extends AbstractSuper{
// Override 규칙
// 접근지정자는 광의로 변경가능, 반환형, method명, 매개변수는 동일
@Override
public void absMethod() {
System.out.println("Override한 absMethod");
}
@Override
public String absMethod1(int i) {
System.out.println("Override한 absMethod1");
return String.valueOf(i);
}
public static void main(String[] args) {
AbstractSub as = new AbstractSub();
as.absMethod();
System.out.println(as.absMethod1(100));
}
}
abstract class Person {
public abstract void paint();
}
class HongGilDong extends Person {
@Override
public void paint() {
System.out.println("동양화를 그린다.");
}
}
class Clark extends Person {
@Override
public void paint() {
System.out.println("서양화를 그린다.");
}
}
class UsePerson {
public static void main(String[] args) {
HongGilDong gd = new HongGilDong();
Clark superman = new Clark();
gd.paint();
superman.paint();
}
}
인터페이스
- 다중상속의 장점을 사용하기위해 사용
- 기능추가를 손쉽게 할 수 있다.
-
약결합의 구현으로 객체간 유연성을 향상시킬 수 있다
- 약결합, 응집도 높은 프로그램이 좋은 프로그램
-
객체화는 안됨
- 구현클래스가 생성되면 그 주소는 저장가능
- 즉, is-a 관계의 객체화 가능
- 여러 부모인터페이스 상속가능
- jdk 1.8에서부터 Default method가 추가됨
- 일을 할 수 있는 { }를 가진 method
- abstract method를 가진다
접근지정자 interface 인터페이스명 extends 부모인터페이스명, ... {
// 상수
// abstract method, interface에선 abstract 사용안해도 추상메소드
접근지정자 반환형 method명(매개변수,..);
접근지정자 abstract 반환형 method명(매개변수,..);
// default method
접근지정자 default 반환형 method명(매개변수명,.. ) {
}
}
/* 접근지정자
public (패키지 외부에서 접근가능)
default (패키지 접근지정자, 패키지 내에서만 접근 가능)
*/
인터페이스 상속, 구현 예제
- 인터페이스는 여러 부모인터페이스를 상속할 수 있다.
- 인터페이스간 상속 시 추상 method를 Override하지 않는다.
- 구현 클래스가 모든 추상 method를 Override한다.
public interface InterA {
public String msgA();
}
public interface InterB {
public String msgB();
}
public interface SuperInterface extends InterA, InterB {
// 상수
public static final int FLAG_VALUE = 12;
// 추상메소드
// "abstract" 없어도 abstract method다.
public void methodA();
public abstract void methodB(String i);
}
// 인터페이스를 구현하는 클래스
public class InterfaceImplements implements SuperInterface {
@Override
public String msgA() { // InterA
return "오늘은 월요일";
}
@Override
public String msgB() { // InterB
return "내일은 화요일";
}
@Override
public void methodA() { // SuperInterface
System.out.println("methodA");
}
@Override
public void methodB(String i) { // SuperInterface
System.out.println("methodB i=" + i);
}
public void test() { // InterfaceImplements
System.out.println("test method");
}
public static void main(String[] args) {
// 자식클래스로 객체화하면 모든 method 호출 가능
InterfaceImplements ii = new InterfaceImplements();
System.out.println("-----InterfaceImplements Instantiation-----");
System.out.println(ii.msgA());
System.out.println(ii.msgB());
ii.methodA();
ii.methodB("Hi");
ii.test();
// is-a 관계의 객체화
// is-a 관계의 객체화는 메소드 접근에 제한을 줄 수 있다.
System.out.println("-----SuperInterface is-a-----");
SuperInterface si = new InterfaceImplements();
System.out.println(si.msgA());
System.out.println(si.msgB());
si.methodA();
si.methodB("hi");
System.out.println("-----InterA is-a-----");
InterA ia = new InterfaceImplements();
System.out.println(ia.msgA());
System.out.println("-----InterB is-a-----");
InterB ib = new InterfaceImplements();
System.out.println(ib.msgB());
// interface는 객체화되지 않는다.
// InterA ia1 = new InterA();
}
}
default method
- 인터페이스 내부에 일을 기술할 수 있는 method
- default method를 사용하게 되면 인터페이스가 추상클래스와 비슷해짐
public interface UseDefault {
public void test();
public default void temp() {
System.out.println("default method - temp method");
}
}
public class UseDefaultMethod implements UseDefault {
@Override
public void test() {
System.out.println("Override한 method");
}
public static void main(String[] args) {
// 자식클래스로 객체화
UseDefaultMethod udm = new UseDefaultMethod();
udm.test();
udm.temp(); // default method
// is-a 관계의 객체화
UseDefault ud = new UseDefaultMethod();
ud.test();
ud.temp(); // default method
}
}