8. 추상클래스
추상클래스는 new로 인스턴스 생성이 불가하다
추상 메서드를 포함하면 추상 클래스
추상 클래스 안에는 추상 메서드와 구체적으로 구현된(보통의 메서드)메서드 모두 존재
{}가 있으면 코드가 없는 것이지 구현이 안된 건 아니기때문에 추상 메서드가 아님
abstract 키워드가 이쓰면 추상 클래스..
추상 클래스를 상속받은 애들이 구현을 함
package abstractex;
public abstract class Computer {
// 지금 구현할 수 없는 메서드를 추상메서드로 구현한다
public abstract void display();
public abstract void typing();
public void turnOn() {
//구현된 메서드도 있다
System.out.println("전원을 켭니다");
}
public void turnOff() {
//구현된 메서드도 있다
System.out.println("전원을 끕니다");
}
}
추상 메서드를 선언하는 클래스는 추상 클래스여야함
상속받은 하위 클래스는 추상 메서드를 모두 구현하지 않으면 추상클래스로 선언해줘야한다
추상클래스는 나를 상속받아서 너네가 구현을 해라.. 고 만든..
상속 받은 클래스가 추상 메서드를 모두 구현하지 않으면 추상 클래스가 됨
추상 메서드가 포함된 클래스는 구현코드가 없기 때문에 인스턴스화될 수 없음
⁕ 모든 코드가 구현되어있어도 abstract 키워드가 있으면 인스턴스화될 수 없다
package abstractex;
public class ComputerTest {
public static void main(String[] args) {
Computer computer = new MyDesktop();
Computer computer2 = new Notebook();
computer.typing();
computer2.display();
}
}
컴퓨터(abstract) - 데스크탑(abstract- 일부 추상 메서드만 구현) - 마이 데스크탑(나머지 구현해서 not abstract)
package abstractex;
public abstract class Desktop extends Computer{
@Override
public void display() {
System.out.println("내 컴퓨터");
}
}
package abstractex;
public class MyDesktop extends Desktop{
@Override
public void typing() {
System.out.println("나머지 메서드 구현");
}
}
컴퓨터(abstract) - 노트북(모두 구현해서 not abstract)
package abstractex;
public class Notebook extends Computer {
@Override
public void display() {
System.out.println("display method in notebook");
}
@Override
public void typing() {
System.out.println("typing method in notebook");
}
}
run은 전체적인 시나리오를 담당하는 메서드로 변경되면 안됨
하위 클래스에서 재정의하도록 하면 안됨 -> final키워드 필요
final을 사용하면 하위 클래스애서 메서드를 재정의할 수 없음
* 클래스에 final키워드를 사용하게 되면 더이상 상속할 수 없는 클래스가 됨
package template;
public class CarTest {
public static void main(String[] args) {
Car aicar = new AICar();
Car manualcar = new ManualCar();
aicar.run();
manualcar.run();
}
}
run을 템플릿 메서드라고 함(전체적 흐름을 정의)
final 키워드
- 변수에 사용하면 값이 변경될 수 없는 상수가 됨
-> 값을 한번만 할당할 수 있음
- 메서드에 사용하면 재정의 불가
- 클래스에 사용하면 상속되지 않음
9. 인터페이스 이해하기
인터페이스: 추상 메서드로만 이루어진 클래스 -> 인터페이스는 인스턴스화될 수 없다
인터페이스의 메서드: public abstract
변수: public static final == 상수
package interfaceex;
public interface Calc {
// 인터페이스 안에서 변수를 선언하면 public static final이 자동으로 부여됨 -> 상수화
// 인스턴스 생성시에 생성되는 변수가 아니므로 Calc.ERROR로 접근할 수 있음
int ERROR = -99999;
// 인터페이스 안에서 메서드를 선언하면 public abstract가 자동으로 부여됨
int add(int num1, int num2);
int substracts(int num1, int num2);
int times(int num1, int num2);
int divides(int num1, int num2);
}
package interfaceex;
public abstract class Calculator implements Calc{
@Override
public int add(int num1, int num2) {
return num1+num2;
}
@Override
public int substracts(int num1, int num2) {
return num1-num2;
}
}
->interface는 implement를 사용해서 상속받는다
package interfaceex;
public class CompleteCalculator extends Calculator {
@Override
public int times(int num1, int num2) {
// TODO Auto-generated method stub
return num1*num2;
}
@Override
public int divides(int num1, int num2) {
if(num2==0) {
return Calc.ERROR;
}
return num1/num2;
}
}
-> class는 extends를 사용해서 상속받는다
package interfaceex;
public class CalculatorTest {
public static void main(String[] args) {
int num1=10;
int num2=2;
Calc calculator = new CompleteCalculator();
System.out.println(calculator.add(num1, num2));
System.out.println(calculator.substracts(num1, num2));
System.out.println(calculator.times(num1, num2));
System.out.println(calculator.divides(num1, num2));
}
}
인터페이스의 기본 요소는 상수와 추상메서드
+ 자바 8 이후 디폴트 메서드, 정적 메서드, 9부터 프라이빗 메서드 추가됨
디폴트 메서드 default
인터페이스 내부에서 디폴드로 선언된 메서드는
인터페이스를 구현한 클래스들이 모두 공유할 수 있는 기본 메서드가 된다
default void description(){}
-> new로 인스턴스를 만든 후에 사용 가능
-> 여러 인터페이스를 매번 구현하는 번거로움 방지
재정의 가능
정적 메서드 static
인스턴스 생성과 관계없이 인터페이스 이름.메서드로 바로 사용 가능
package interfaceex;
public interface Calc {
// 인터페이스 안에서 변수를 선언하면 public static final이 자동으로 부여됨 -> 상수화
// 인스턴스 생성시에 생성되는 변수가 아니므로 Calc.ERROR로 접근할 수 있음
int ERROR = -99999;
// 인터페이스 안에서 메서드를 선언하면 public abstract가 자동으로 부여됨
int add(int num1, int num2);
int substracts(int num1, int num2);
int times(int num1, int num2);
int divides(int num1, int num2);
default void description() {
System.out.println("정수의 사칙연산을 계산합니다");
}
static int total(int[] arr) {
int total=0;
for(int num: arr) {
total+= num;
}
return total;
}
}
package interfaceex;
public class CalculatorTest {
public static void main(String[] args) {
int num1=10;
int num2=2;
Calc calculator = new CompleteCalculator();
System.out.println(calculator.add(num1, num2));
System.out.println(calculator.substracts(num1, num2));
System.out.println(calculator.times(num1, num2));
System.out.println(calculator.divides(num1, num2));
calculator.description();
Calc newCalc = new CalcNew();
newCalc.description();
int[] numbers = new int[] {1,2,3,4,5,6,7,8,9,10};
// 인스턴스의 생성(new)과 관계없이 Calc.으로 바로 사용가능
int sum = Calc.total(numbers);
System.out.println(sum);
}
}
인터페이스 타입으로 사용가능 ?????????
프라이빗 메서드 private (Java 9)
인터페이스를 구현한 클래스에서 사용하거나 재정의할 수 없음
인터페이스 내부에서만 기능을 제공하기 위해 구현
프라이빗 일반 메서드/ 정적 메서드가 있음 -> 일반은 디폴트에서/ static은 static에서 사용함
여러개의 인터페이스를 implements할 수 있다
package interfaceex;
public interface Buyer {
void buy();
default void order() {
System.out.println("buyer's order method ");
}
}
package interfaceex;
public interface Seller {
void sell();
default void order() {
System.out.println("seller's order method");
}
}
package interfaceex;
public class Customer implements Buyer, Seller {
@Override
public void sell() {
System.out.println("customer sells");
}
@Override
public void buy() {
System.out.println("customer buys");
}
@Override
public void order() {
System.out.println("customer overrides order method");
}
}
-> 인터페이스를 2개 이상 구현할 때 인터페이스에 속한 메서드 이름이 중복되면 둘 중 하나를 쓰거나 오버라이딩을 한다
package interfaceex;
public class CustomerTest {
public static void main(String[] args) {
Customer customer = new Customer();
customer.buy();
customer.sell();
customer.order(); //customer overrides order method
Buyer buyer = customer;// customer가 Buyer타입에 대입될 수 있음 -> 타입에 바인딩되므로 buy, order 메서드만 호출 가능
buyer.order(); //메서드는 가상 메서드이므로 customer에서 재정의된 order가 호출됨 -> customer overrides order method
Seller seller = customer;
seller.order(); //customer overrides order method
}
}
10. 인터페이스 활용
인터페이스를 설계한다
인터페이스를 클래스가 implement한다~!
고객전화- 스케쥴러(다음 콜을 가져오고, 상담원에게 분배)
구현 방법(정책)- 라운드 로빈/ 리스트잡/ 프라이오리티 얼로케이션
클라이언트 측에서는 인터페이스가 중요함(사용방법!)
-> 사용할 때는 어떤 메서드가 사용되는지, 어떤 매개변수가 필요한지만 알면 되기때문에 실질적인 구현 방식은 알 필요가 없음
클라이언트 프로그램에 대한 일종의 계약사항을 명시한 스펙이라고 할 수 있음
객체는 인터페이스가 제공하는 함수를 구현한 것이고
클라이언트코드는 인터페이스의 정의를 이용해서 사용함 ex. jdbc
인터페이스를 사용해서 strategy pattern을 구현할 수 있음
sorting argorithm을 strategy design pattern을 이용해서 구현해보자~
Sort 인터페이스를 implement한 bubble, insertion, quick class가 있고 각각 구현함
package sort;
public interface Sort {
void ascending(int[] arr);
void descending(int[] arr);
default void description() {
System.out.println("sort description");
}
}
package sort;
public class BubbleSort implements Sort{
@Override
public void ascending(int[] arr) {
System.out.println("bubble ascending");
}
@Override
public void descending(int[] arr) {
System.out.println("bubble descending");
}
@Override
public void description() {
// 굳이 super로 불러주지 않아도 오버라이드 가능한 건 알고 있지
Sort.super.description(); // sort description
System.out.println("bubble sort description");
}
}
package sort;
import java.io.IOException;
public class SortTest {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
System.out.println("정렬 방식을 선택하세요");
System.out.println("B: bubble sort");
System.out.println("Q: quick sort");
System.out.println("I: insertion sort");
int ch=System.in.read();// 입력값을 받음 -> 예외처리를 해줘야함
Sort sort = null;
if(ch=='B'|| ch=='b') {
sort= new BubbleSort();
}
else if(ch=='Q'|| ch=='q') {
sort= new QuickSort();
}
else if(ch=='I'|| ch=='i') {
sort= new InsertionSort();
}
else {
System.out.println("지원하지 않는 기능입니다.");
return;
}
int [] myarray = new int[10];
// 호출 - 입력받는 알팜벳에 따라서 다양한 구현 가능(다형성)
sort.ascending(myarray);
sort.descending(myarray);
sort.description();
}
}
JDBC
connection: 자바에서 db에 연결할 때 필요한 객체
인터페이스임
정의되어있는 메서드를 구현하면 사용할 수 있음 -> 우리는 오라클이나 mySQL이 구현해놓은 메서드를 사용
인터페이스 구현과 클래스 상속 사용
package bookshelf;
public interface Queue {
void enQueue(String title);
String deQueue();
}
package bookshelf;
import java.util.ArrayList;
public class Shelf {
protected ArrayList<String> shelf;
public Shelf() {
shelf=new ArrayList<String>();
}
public int getCount() {
return shelf.size();
}
}
인터페이스 구현 및 클래스 상속
package bookshelf;
public class BookShelf extends Shelf implements Queue{
@Override
public void enQueue(String title) {
shelf.add(title);
}
@Override
public String deQueue() {
return shelf.remove(0);//후입선출이면 shelf.size()-1
}
}
package bookshelf;
public class BookShelfTest {
public static void main(String[] args) {
Queue bookshelf = new BookShelf();
bookshelf.enQueue("책 제목1");
bookshelf.enQueue("책 제목2");
bookshelf.enQueue("책 제목3");
System.out.println(bookshelf.deQueue());
System.out.println(bookshelf.deQueue());
System.out.println(bookshelf.deQueue());
}
}
선입 선출이므로 책 제목1->책 제목2->책 제목3 순으로 출력된다