위의 그림처럼 A와 B의 경우 같은 부모를 가지고 상속을 받지 않기 때문에 A와 B를 서로 전해줄 수 없다.
특징
DatabaseChild와 cloudDatabaseChild의 경우 모두 Parent 타입이다.
DatabaseChild객체와 CloudDatabaseChild는 모두 Parent타입의 참조변수로 참조할 수 있다.
Parent parent = new DatabaseChild();
Parent parent = new CloudDatabaseChild();
Parent로부터 상속받은 메소드를 전부 재정의 했기 때문에 사용법이 동일하다.
DatabaseChild와 CloudDatabaseChild는 서로를 대체할 수 있다.
사용법이 동일하다는 뜻은 대체가 가능하는 뜻이다.
다형성 발현에 필요한 필수사항
소스코드의 변경없이 사용하는 객체를 교체하기 위한 필요조건
자식클래스들이 같은 부모의 클래스이며, 같은 부모의 자식이어야 한다.
부모타입의 참조변수가 모든 자식 객체를 참조할 수 없다.
자식클래스에 구현된 기능들이 (메소드들의) 사용법이 동일해야한다.
자식클래스들이 부모로부터 물려받은 기능을 메소드 재정의를 사용해서 자신에게 맞게 재정의 해야한다.
모든 자식 클래스들의 사용법이 동일해진다.
사용하는 클래스에서는 부모타입의 참조변수로 필드를 정의해야 한다. UserService처럼 구현하는 클래스에서는 부모타입의 참조변수를 매개변수로, 필드로 정의해야한다.
자식객체의 종류에 상관없이 참조가 가능하다.
사용하는 클래스에서는 부모타입의 참조변수로 사용이 가능한 메소드만 사용해야한다.
사용하는 클래스에서는 생성자, Setter메소드를 통해서 필요한 객체를 제공받아야한다.
Setter메소드로 정의를 하여, 전달받은 매개변수를 입력하도록 작성, 이후 출력하는 기능을 작성해야한다.
databaseChild와 CloudDatabaseChild의 경우 1. Parent로 부터 상속을 받고 있고, 2. 서로 동일한 사용법을 가지고 있다.
UserService내용에 변화없이 사용하는 객체를 변경할 수 있다.
소스코드의 변경없이 사용하는 객체가 가능해졌다.
확장성이 높아진다.
유지보수가 쉬워진다.
다형성을 발휘할 수 있다.
필요조건으로는
같은 부모의 자식이어야 한다.
사용방법이 동일해야한다. -->메소드의 재정의를 꼭 해야한다.
OracleDatabaseAccess와 MySQLDatabaseAccess는 같은 부모의 클래스이다.
OracleDatabaseAccess와 MySQLDatabaseAccesss는 사용방법이 다른 클래스이다.
OracleDatabaseAccess나 MySQLDatabaseAccess는 서로를 대체할 수 없다.
parent의 참조 변수로 OracleDatabaseAccess의 기능을 실행할 수 없다. 만약 사용하고 싶다면? 강제 형변환만이 사용할 방법!!!
parent의 참조 변수로 MySQLDatabaseAccess의 메소드가 사용되었다. 강제형변환없이 재정의 메소드 실행이 가능하다.
사용법이 똑같아지게 만들어주는 것...!! 그게 바로
추상화
이다.
추상화(Abstraction)
추상화는 객체에서 공통된 속성와 기능을 추출하는 것이다.
자바에서 추상화는 공통된 속성과 기능을 모아서 추상클래스 (Abstract Class)나 인터페이스(Interface)를 정의하는 것이다.
공통 속성은 변수나 상수로 표현하고 기능은 추상메소드로 표현한다.
추상화를 통해서 하위 클래스들이 구현해야할 공통기능을 정의할 수 있다.
추상메소드
추상메소드는 공통기능을 추상화하는 메소드이다.
추상메소드는 구현부가 없는 메소드이다.
추상메소드는 추상클래스와 인터페이스에만 정의할 수 잇다.
일반클래스 (구현하는 클래스 )는 추상메소드를 보유할 수 없다. (구현부가 없기 때문에, 생성자 메소드랑 다른이야기이다.)
만약, 추상메소드를 상속받았다면 반드시 메소드 재정의를 통해서 구현부가 있는 메소드로 만들어야한다.
abstract의 경우 Body가 없이 선언부만 존재한다고 생각하면 된다.
인터페이스 (Interface)
인터페이스는 하위 클래스에 특정한 메소드가 반드시 존재하도록 강제할 때 사용된다.
인터페이스는 모든 하위클래스의 사용법(메소드의 실행방법)을 통일시키는 표준으로 사용된다.
하위클래스는 인터페이스에 정의된 추상화된 메소드를 구현(재정의)할 책임이 있다.
하위클래스는 동시에 여러개의 인터페이스를 구현할 수 있다.
interface의 경우 자바 8 이전과 이후로 문법상으로 바뀐부분이 있다.
클래스와 인터페이스 (자바 8이전 문법의 기준)
클래스 (class)
멤버변수, 클래스 변수, 생성자, 멤버메소드, 클래스 메소드를 보유할 수 있다(필드, static변수-클래스저장공간에서 관리하는 변수, 클래스 name과 동일하고, overLoding하는 생성자, 메소드, static메소드-클래스저장공간에서 관리하는 메소드)
new연산자를 사용해서 객체를 생성할 수 있다.
단일 상속만 지원한다.
객체 생성에 설계되는 설계도 이다.
객체의 속성(성질, 고유한 값)을 저장하는 변수가 있다.
객체의 기능이 구현된 메소드가 있다.
객체의 초기화를 담당하는 생성자 메소드가 있다.
인터페이스 (interface)
상수, 추상메소드만 보유할 수 있다.
추상메소드는 구현부가 없는 메소드이다.
상수의 경우 인터페이스는 필수로 정의해야하는 메소드를 가지고 있기 때문에 값이 변하지 않기 위해서 public static FINAL 의 형태의 상수를 필드로 가지고 있다.
객체를 생성할 수 없다.
다중상속을 지원한다. --->부모가 2개여도 된다.
구현클래스가 반드시 구현할 기능을 정의하는 표준(스펙)이다. -->인터페이스는 표준안이다. 빈껍데기이다.
구현클래스가 재정의 할 기능에 대한 명세서다.
구현부가 없는 추상메소드는 구현클래스가 재정의 할 기능에 대한 명세서이다.
구현클래스와 인터페이스
구현클래스는 하나이상의 인터페이스를 구현한 클래스다.
구현클래스는 구현부가 없는 추상메소드를 포함할 수 없다.
만약 구현부가 없는 메소드를 상속받으면 무조건!!!!!!!!!!!!!!!!!!!!!!!!!!재정의해야한다.
구현클래스는 인터페이스에 정의된 구현부가 없는 메소드를 전부!!재정의한 클래스이다.
구현클래스에는 구현부가 없는 메소드가 하나도 없다.
구현클래스에는 implements 키워드를 사용해서 자신이 구현할 기능이 선언되어 있는 인터페이스들을 지정할 수 있다.
public class 구현클래스 implements 인터페이스1, 인터페이스2,...., 인터페이스 N{
1. 각 인터페이스에 정의된 구현부가 없는 추상메소드를 전부 재정의한다.
2. 구현부가 없는 추상메소드가 하나라도 재정의 되지 않으면 구현 클래스는 컴파일 오류가 발생된다.
}
구현클래스는 지금까지 배운 것이 구현클래스이다. 인터페이스와 연관하여 생각하면 된다.
인터페이스의 추상화 클래스를 구체화 시킨 클래스이다.
따라서, 특정인터페이스를 구현한 구현클래스들은 언제나 동일한 구현 메소드를 가지고 있다. 즉, 인터페이스를 상속한 구현클래스는 인터페이스의 타입의 부모를 가지고 있다고 생각하면 된다. 부모 = 인터페이스
인터페이스 내부에 추상메소드가 2개가 있다면 무조건 2개를 구현해야한다.
부모는 클래스와 인터페이스로 가질 수 있다.
차이점
인터페이스 설정하기
차는 출발, 정지, 속도변경, 속도조회 기능이 있어야한다.
인터페이스는 전부 추상메소드이기 때문에 public abstract 를 생략할 수 있다.
public abstract void start();//이게 추상메소드, 출발 public abstract void stop();//정지 /*public abstract*/ void speedUp(); //스피드 올림 public abstract void speedDown(); //스피드내림 public abstract int getCurrentSpeed(); //현재속도조회
구현부가 없는 추상메소드를 정의하기
추상메소드는 구현부가 없는 메소드이다.
추상메소드는 abstract키워드를 포함해야한다.
인터페이스에서는 public abstract를 생략할 수 있다.
이 인터페이스를 구현하는 구현클래스가 반드시 재정의할 기능을 추상메소드로 정의한다.
impements 는 구현하다, 구체화 하다의 의미를 갖는다
모든 자동차의 속도는 최저 0미만의 속도가 나올 수 없고, 200키로 이상의 속도가 나올 수 없다.
/*public static final */int MIN_SPEED = 0; public static final int MAX_SPEED = 200;
이렇게 상수로 지정해줄 예정이다.
상수정의하기
상수는 변하지 않는 값의 저장소이다.
상수는 public static final키워드를 포함한다.
상수의 이름은 전부 대문자로 쓰고, 두단어 이상일 때는 중간에 _를 삽입한다.
인터페이스에서는 public static Final를 생략할 수 있다.
public 공개되있는 static공통의 클래식 변수 Final 상수이다.
강제하기 때문에
인터페이스의 경우
강제하기 때문에 구현클래스의 표준(스펙) 이 된다.
구현클래스가 구현할 기능을 지정한다.
구현클래스들의 사용법이 똑같아 지도록 하는 것이 목적이다.
위의 그림을 확인해보면 집을 만드는 사람은 어떤 창문을 사용할 지 모르는 상태에서 창문의 부모를 작성하고 구현해냈다. 즉, 이 집에서는 window 인터페이스를 구현한 객체만 사용할 것이다라는 의미로 사용할 수 있다.(표준사용) window를 만드는 사람은 window의 종류만 중요하고 어떤집에 놓을 것인지는 중요하지 않다. 즉, 우리는 window인터페이스를 구현한 객체만 생성한다는 의미로 볼 수 있다. (표준생산) 전체적으로 표준안을 둔 상태로 구현해낸것을 확인 할 수 있다.
참조변수로 사용할 수 있는 것
부모클래스타입의 참조변수는 자식객체를 참조할 수 있다.
ParentClass parent = new Child();
부모인터페이스는 자식객체를 참조할 수 있다.
ParentInterface parent = new Child();
생성된 객체와 같은 타입의 참조변수는 객체를 참조할 수 있다.
Child child = new Child();
Object 타입의 참조변수는 자식객체를 참조할 수 있다.
Object topParent = new Child();
즉, 자식객체를 참조할 수 있는 참조변수는?? 나 자신, 부모 클래스, 부모 인터페이스, 최고조상인 Object라는 것을 알 수 있다.