# 추상 클래스
## 추상 클래스 활용 (일부 다형성 보장)
- 키워드 : abstract - extends
- Animal의 eat 메서드를 Dog, Cat 클래스가 상속받아 재정의(Override) 하게되면 아래와 같이 호출하여 작동.
// Animal에 존재하는 eat() 메서드.
public void eat() {
System.out.println("?");
}
Animal dog = new Dog();
dog.eat(); // dog에서 재정의(Override)한 것으로 출력.
animal cat = new Cat();
cat.eat(); // cat에서 재정의(Override)한 것으로 출력.
- 재정의를 하게 되면 하위클래스에서 재정의한 값으로 출력 됨.
- 재정의를 하지 않게 되면 상위 클래스에서 정한 값으로 출력 됨.
- 추상 메서드 (키워드 : abstract) : 상위 클래스에 존재하는 메서드를 하위 클래스에서 재정의 하지 않을 때, 상위 클래스에서 정한 값이 출력되지 않도록할 때, 상위 클래스에서 해당하는 메서드를 추상 메서드로 처리하여 구현부를 없앨 수 있다. 구현부가 없어지고 원형(프로토타입)만 남게 됨.
// 기존 메서드
public void eat() {
System.out.println("?");
}
// 추상 메서드
public abstract void eat();
- 추상 클래스 (불완전한 객체) : 추상 메서드를 1개라도 갖고 있으면 해당 클래스는 추상 클래스가 됨.
public abstract class Animal {
public abstract void eat(); // 추상 메서드
public void move() { // 구현 메서드
System.out.println("움직인다.");
}
}
- 추상 클래스는 불완전한 메서드를 갖고있는 불완전한 객체이므로 아래와 같이 객체 생성 불가. (부모 역할만 가능)
Animal ani = new Animal(); // 추상 클래스는 불가능.
- 하위 클래스는 추상 메서드 반드시 재정의 : 부모(상위) 클래스가 추상 클래스가 되면, 자식(하위) 클래스는 반드시 추상 메서드를 구현해야 함(반드시 재정의 해야 함).
- 추상 클래스는 서로 기능이 비슷한 클래스를 묶을 때 사용한다.
## 추상 클래스 (실습)
public abstract class Animal extends Object {
// 추상 클래스(불완전한 객체) -> Animal ani = new Animal(); 불가능.
// 추상 클래스는 부모의 역할만 가능.
public abstract void eat(); // 추상 메서드(불완전한 메서드)
public void move() {
System.out.println("무리를 지어서 이동합니다.");
}
}
public class Cat extends Animal {
// 이름, 나이, 종 등 : 상태정보 존재.
@Override
public void eat() {
System.out.println("고양이 처럼 먹는다.");
}
public void night() {
System.out.println("고양이는 밤에 눈에서 빛이 난다.");
}
public Cat() {
super(); // new Animal();
}
}
public class Dog extends Animal {
// 이름, 나이, 종 등 : 상태정보 존재.
// 재정의(override) : 추상 메서드 재정의 하지 않는 경우 에러 발생.
// 부모(Animal)이 추상 클래스 이므로 부모의 추상 메서드 재정의 필수.
public void eat() {
System.out.println("멍멍이 처럼 먹는다.");
}
public Dog() {
super(); // new Animal();
}
}
public class TPC26 {
public static void main(String[] args) {
// Animal의 eat 메서드를 반드시 하위 클래스가 재정의(Override)
Animal d = new Dog();
d.eat(); // 재정의로 인해 Dog의 eat 출력.(다형성 보장됨)
d.move();
d = new Cat();
d.eat(); // 재정의로 인해 Cat의 eat 출력.
d.move();
((Cat)d).night(); // DownCasting
}
}
# 인터페이스 (100% 다형성 보장)
- 키워드 : interface - implements (구현하다)
- 인터페이스 : 서로 기능이 다른 클래스를 묶을 때 인터페이스를 사용한다. 100% 추상 메서드만 가능하며, 구현된 메서드를 가질 수 없다. 상위 클래스가 갖고 있는 메서드를 하위 클래스가 100% 재정의 해야 한다.
- 하위 클래스의 동작 방식을 몰라도 인터페이스로 100% 동작시킬 수 있다.
## 인터페이스 (실습)
- 인터페이스는 상수(final static) 사용 가능하다.
public interface RemoCon { // 객체생성 불가. RemoCon con = new RemoCon(); 불가.
// 상수(final static) 사용 가능.
int MAXCH = 100; // public static final int MAXCH = 100; 인데 생략되어 있음.
int MINCH= 1;
// 추상 메서드
public void chUp(); // abstract 생략됨.
public void chDown();
public void internet();
}
public class TV implements RemoCon {
@Override
public void chUp() {
System.out.println("채널이 올라감.");
}
@Override
public void chDown() {
System.out.println("채널이 내려감.");
}
@Override
public void internet() {
System.out.println("인터넷이 됨.");
}
}
public class Radio implements RemoCon {
@Override
public void chUp() {
System.out.println("채널이 올라감.");
}
@Override
public void chDown() {
System.out.println("채널이 내려감.");
}
@Override
public void internet() {
System.out.println("인터넷이 됨.");
}
}
# 추상클래스와 인터페이스
- 추상클래스와 인터페이스의 궁극적인 목적 : 다형성을 보장하기 위함.
- 부모의 역할로 사용함.
- 부모 클래스를 추상클래스 or 인터페이스로 만들어야 다형성을 보장할 수 있다.
- 하위(자식) 클래스에서 추상메서드는 반드시 재정의(Override) 해야 한다.
|
추상 클래스 (불완전한 객체) |
인터페이스 (불완전한 객체) |
키워드 |
abstract |
interface |
extends |
implements |
공통점 |
다형성을 보장하기 위해 등장함. 객체를 생성할 수 없다. (new 불가) 하위(자식) 클래스에 의해 구현되어야 한다. (재정의(Override) 필수) 부모(상위) 클래스의 역할로 사용한다. (UpCasting으로 객체를 생성) 추상 메서드를 가진다. |
차이점 |
서로 기능이 비슷한 클래스를 묶을때 사용. 구현 매서드 / 추상 메서드 함께 사용 가능. 구현 메서드를 가질 수 있다. |
서로 기능이 다른 클래스를 묶을때 사용. 100% 추상 메서드로 이루어 진다. 구현 메서드를 가질 수 없다. 다중상속 형태를 지원 함. final static(상수) 멤버 변수를 가질 수 있다. |
## 추상 클래스와 인터페이스 (실습)
public interface RemoCon { // 객체생성 불가. RemoCon con = new RemoCon(); 불가.
// 상수(final static) 사용 가능.
int MAXCH = 100; // public static final int MAXCH = 100; 인데 생략되어 있음.
int MINCH= 1;
// 추상 메서드
public void chUp(); // abstract 생략됨.
public void chDown();
public void internet();
}
public class TV implements RemoCon {
int currCH = 70;
@Override
public void chUp() {
if (currCH < RemoCon.MAXCH) {
currCH++;
System.out.println("채널이 올라감. {" + currCH + "}");
} else {
currCH = 1;
System.out.println("채널이 올라감. {" + currCH + "}");
}
}
@Override
public void chDown() {
if (currCH > RemoCon.MINCH) {
currCH--;
System.out.println("채널이 내려감. {" + currCH + "}");
} else {
currCH = 100;
System.out.println("채널이 내려감. {" + currCH + "}");
}
}
@Override
public void internet() {
System.out.println("인터넷이 됨.");
}
}
public class TPC28 {
public static void main(String[] args) {
RemoCon tv = new TV();
for (int i = 0; i < 40; i++) {
tv.chUp();
}
for (int i = 0; i < 40; i++) {
tv.chDown();
}
tv.internet();
}
}
# 인터페이스(규약)와 JDBC의 관계
## JAVA JDBC Programming
- 자바에서 JDBC 프로그래밍을 하기위해 벤더에서 제공하는 클래스를 이용해야 한다. 벤더에서 제공하는 클래스가 통일되어 있지 않으면 자바 개발자들은 모든 데이터베이스의 동작을 알고 있어야 JDBC 프로그래밍이 가능해진다. (사실상 불가능)
- DB벤더(공급자) : 오라클, My-SQL, MS-SQL 등 존재
1. 오라클
class JavaOracle {
// 접속동작
oracleConnect(){
}
}
2. My-SQL
class JavaMySql {
// 접속동작
mysqlConnect(){
}
}
3. MS-SQL
class JavaMsSql {
// 접속동작
mssqlConnect(){
}
}
- 위와 같은 문제를 해결하기 위해 인터페이스 사용.
1. 상위클래스(부모) 에서 인터페이스 java.sql.* 생성.
public interface Connection {
// 접속동작
getConnection(String url, String user, String passwd);
}
2. 하위클래스(자식) 에서 구현클래스를 만들게 함. (Driver class)
- 벤더에서 통일된 메서드 이름을 이용.
- Oracle Driver, MySQL Driver, MSSQL Driver
## 인터페이스와 JDBC의 관계 (실습)
public interface Dbconnect {
public void getConnection(String url, String user, String passwd);
}
public class JavaOracle implements Dbconnect {
@Override
public void getConnection(String url, String user, String passwd) {
System.out.println("오라클 DB가 접속 됩니다.");
}
}
public class JavaMySQL implements Dbconnect {
@Override
public void getConnection(String url, String user, String passwd) {
System.out.println("MySQL DB가 접속 됩니다.");
}
}
public class TPC29 {
public static void main(String[] args) {
// 드라이버 클래스 가상으로 만들어서 작업(실제 연결 X)
// Oracle, MySQL, MSSQL 등 -> Driver class
Dbconnect conn = new JavaOracle();
conn.getConnection("url", "abc", "12345");
conn = new JavaMySQL();
conn.getConnection("url", "bbb", "12345");
}
}
# 인터페이스의 상속관계
## 인터페이스와 인터페이스의 상속 관계
1. 인터페이스 A
public interface A {
public void m();
}
2. 인터페이스 A를 상속받은 인터페이스 B
public interface B extends A {
public void z();
}
3. 인터페이스 B를 상속받은 클래스 X -> 반드시 재정의(Override) 해야 함.
public class X implements B {
public void m() {
}
public void z() {
}
}
이때 객체 생성은 아래와 같이 진행.
B r = new X();
A r = new X();
## 다중상속 관계에 있는 클래스 구조
- Animal (abstract class) / Pet (interface) / Robots (interface) 일때..
public class Dog extends Animal implements Pet, Robots {
}