package ex0726;

public class Ex07_interface {
	public static void main(String[] args) {
		int s = Demo7.sum(10);
		System.out.println(s);
		
		Demo7 dm = new DemoImpl7();
		int x = dm.max(5, 10);
		dm.write(x);
	}
}
// interface는 순수하게 선언하는 것만 하는 게 더 좋을 것 같다 = 쌤
interface Demo7 {
	public void write(int n);
	
	// JDK 8부터 가능. 인터페이스를 이용하여 바로 접근 가능
	public static int sum(int n) {
		int s = 0;
		for( int i=1; i<=n; i++) {
			s+=i;
		}
		return s;
	}

	// JDK 8부터 가능. 
	// default 키워드를 이용하여 메소드 구현 가능
	// 구현 클래스에서 재정의 가능
	public default int max(int m, int n) {
		return m > n ? m : n;
	}
}

class DemoImpl7 implements Demo7 {
	@Override
	public void write(int n) {
		System.out.println("결과 : " + n);
		
	}
}

원래 interface는 추상클래스의 일종이므로 선언된 것을 다른 클래스에서 재정의를 하고 그 클래스를 생성해서 재정의된 메소드를 부르는 식 or 다른 클래스에 있는 static 메소드는 객체 생성없이 접근 가능임 여기서는 인터페이스에 구현된 static 클래스도 바로 접근이 가능함을 보았다. 또 default키워드를 이용해 메소드 구현이 가능하다. (이 전에는 틀을 만들어주었기 때문에 굳이 메소드를 구현하지 않고 다른 클래스에서 재정의해서 사용했었다) 물론 구현클래스에서 재정의도 가능하다. 

원래 interface클래스에 선언된 메소드를 구현 클래스에서 재정의를 하지 않으면 안됐는데 default로는 interface에 있는 메소드를 재정의하지 않고도 접근할 수 있다.  

 

package ex0726;

public class Ex06_interface {
	public static void main(String[] args) {
		Store st = new Store();
		
		// Orange ob = new Orange();
		Fruit ob = new Orange();
		st.sell(ob);
		st.sell(new Apple());
		
		
	}
}
interface Fruit {
	public int getPrice();
	public String getName();
}

class Apple implements Fruit {
	@Override
	public int getPrice() {
		return 1000;
	}

	@Override
	public String getName() {
		return "사과";
	}
}

class Orange implements Fruit {
	@Override
	public int getPrice() {
		return 800;
	}

	@Override
	public String getName() {
		return "오렌지";
	}
}

class Store {
	public void sell(Fruit ft) {
		System.out.println(ft.getName() + " - > " + ft.getPrice());
	}
}

인터페이스는 추상 클래스 종류이다.

클래스를 위한 템플릿이다.

 

과일로 친다면

과일의 이름과 가격을 인터페이스의 메소드로 선언해놓음.

Apple 클래스에서 Fruit를 구현했을 때 이름과 가격을 재정의 해야만 컴파일 오류가 발생하지않는다. (이름과 가격이 틀이기 때문에 그 틀에 맞춰서 Apple을 구현한다.) 나중에 Store클래스의 sell메소드에서 Fruit의 틀에 맞춰 생성된 과일들의 객체를 받아 과일의 이름과 가격을 출력해준다.

package ex0726;

public class Ex05_interface {
	public static void main(String[] args) {
		DemoImpl5 di = new DemoImpl5();
		di.print();
	}
}
interface Ademo5 {
	public void print();
}

interface Bdemo5 {
	public void disp();
}

// 인터페이스는 다른 인터페이스를 상속 받을 수 있다.
// 인터페이스는 클래스와 다르게 2개 이상의 인터페이스를 상속 받을 수 있다.
interface Cdemo5 extends Ademo5, Bdemo5 {
	public void sub();
}

class DemoImpl5 implements Cdemo5 {

	@Override
	public void print() {
		System.out.println("print ...");
	}

	@Override
	public void disp() {
		System.out.println("disp ...");
	}

	@Override
	public void sub() {
		System.out.println("sub ...");
	}
	
}

DemoInpl5에서 print() disp() sub()를 재정의 하지 않으면 컴오류! 인터페이스에서 선언된 메소드 들은 구현된 클래스에서 실행하기 위해서 재정의되어야 한다.

'쌍용강북교육센터 > 7월' 카테고리의 다른 글

0726_Ex07_interface : 인터페이스  (0) 2021.07.26
0726_Ex06_interface : 인터페이스  (0) 2021.07.26
0726_Ex04_interface : 인터페이스  (0) 2021.07.26
0726_Ex03_interface 인터페이스  (0) 2021.07.26
0726_Ex02_interface  (0) 2021.07.26
package ex0726;

public class Ex04_interface {
	public static void main(String[] args) {
		Demo4 ob = new Test4(); // up casting
		ob.print();
		ob.disp();
	
	}
}
interface Demo4 {
	public void print();
	public void disp();
}

// 추상 클래스는 인터페이스의 모든 메소드를 구현하지 않아도 된다.
abstract class DemoImple4 implements Demo4 {
	@Override
	public void disp() {
		System.out.println("disp 메소드 ...");
	}
}

class Test4 extends DemoImple4 {
	@Override
	public void print() {
		System.out.println("print 메소드 ...");
	}
}

'쌍용강북교육센터 > 7월' 카테고리의 다른 글

0726_Ex06_interface : 인터페이스  (0) 2021.07.26
0726_Ex05_interface : 인터페이스  (0) 2021.07.26
0726_Ex03_interface 인터페이스  (0) 2021.07.26
0726_Ex02_interface  (0) 2021.07.26
0726_Ex01_abstract : 추상 클래스  (0) 2021.07.26
package ex0726;

public class Ex03_interface {
	public static void main(String[] args) {
		DemoImpl3 di1 = new DemoImpl3();
		di1.print();
		di1.disp();
		di1.sub();
		
		Ademo3 di2 = new DemoImpl3(); // up casting
		Bdemo3 di3 = new DemoImpl3(); // up casting
		
		// di2.print(); // 컴파일 오류. Ademo3 인터페이스에는 print() 메소드가 선언되어 있지 않음.
		((Bdemo3)di2).print();
			// 클래스에 Ademo3과 Bdemo3 인터페이스가 구현되어 있으므로 가능.
			// 만약 Bdemo3 인터페이스가 구현되어 있지 않으면 런타임 오류 발생.
		
		((DemoImpl3)di3).sub(); // 다운 캐스팅
	}
}
interface Ademo3 {
	public void disp();
}

interface Bdemo3 {
	public void print();
}

// 클래스는 2개 이상의 인터페이스를 구현할 수 있다.(다중 상속이 되지 않는 부분을 보충)
class DemoImpl3 implements Ademo3, Bdemo3 { // 이게 중요한 부분!!!

	@Override
	public void print() {
		System.out.println("Bdemo3 인터페이스 메소드 ...");
	}

	@Override
	public void disp() {
		System.out.println("Ademo3 인터페이스 메소드 ...");
	}
	
	public void sub() {
		System.out.println("클래스에 정의된 메소드 ...");
	}
	
}

인터페이스를 여러개 만들어 두고 클래스에 그 여러 개를 상속받을 수 있다! 그렇기에 형제들끼리는 서로 캐스팅될 수 없는데 여기에서는 구현된 인터페이스끼리는 캐스팅이 가능.

package ex0726;

public class Ex02_interface {
	public static void main(String[] args) {
		// Demo2 dm = new Demo2(); // 컴파일 오류. 인터페이스는 추상 클래스의 일종으로 객체 생성 불가

		// 인터페이스는 구현 클래스의 상위 클래스와 유사하다.
		Demo2 dm = new DemoImpl2(); // up casting
		dm.print();
		dm.disp();
		
		// dm.sub(); // 컴파일 오류. 
			// 구현 클래스에는 정의 되어 있지만 인터페이스에는 존재하지 않으므로
		((DemoImpl2)dm).sub(); // down casting
		
		System.out.println(Demo2.A);
		
		// Demo2.B = 50 ; // 컴오류. 인터페이스에 정의된 필드는 final 이므로
		
	}
}
// interface : 선언만 있고 정의가 없는 abstract 클래스의 일종
// 인터페이스 작성
interface Demo2 {
	// 인터페이스 필드는 static final만 가능
	public static final int A = 10;
	int B = 20; // public static final을 붙이지 않아도 public static final
	
	public void print(); // 메소드는 선언만 가능(abstract 메소드)
	public abstract void disp(); // abstract 는 생략 가능
	
	/*
	public void sub() { // 메소드를 정의 하면 컴파일 오류가 발생
		// 
	}
	*/
	
}

인터페이스 클래스에서는 메소드를 대괄호를 넣어서 정의를 하면 안되고, 따옴표를 찍어서 ; 선언만 가능!!

// 인터페이스 구현
// 인터페이스를 구현한 클래스가 추상 클래스가 아닌 경우 인터페이스의 모든 메소드를 재정의 해야 한다.
class DemoImpl2 implements Demo2 {
	@Override
	public void print() {
		System.out.println("print - 인터페이스 메소드 재정의...");		
	}

	@Override
	public void disp() {
		System.out.println("disp - 인터페이스 메소드 재정의...");
	}
	
	public void sub() {
		System.out.println("클래스에 정의된 메소드...");
	}
	
}

인터페이스에서 선안된 메소드를 인터페이스를 구현한 클래스가 꼭 Override를 해야함!

package ex0726;

public class Ex01_abstract {
	public static void main(String[] args) {
		// SortInt si = new SortInt(); // 컴파일 오류. 추상 클래스는 객체 생성 불가.
		// 추상 클래스는 반드시 하위 클래스가 존재하고 하위 클래스를 통해서만 객체를 생성
		
		int[] data = new int[] {40,50,30,35,25};
		// SortInt si = new BubbleSort(); // 업캐스팅
		SortInt si = new SelectionSort();
		
		print("source data : ", data);
		
		si.sort(data);
		
		print("sort data : ", data);
		
	}
	
	public static void print(String title, int[] value) {
		System.out.print(title);
		for(int n : value) {
			System.out.print(n+" ");
		}
		System.out.println();
	}
}

추상 클래스 (abstract class)

  • 선언만 있고 정의가 없는 하나 이상의 추상 메소드를 갖는 클래스. 
  • 추상 메소드가 하나 이상 존재하는 경우 반드시 추상 클래스로 선언 해야 한다.
  • 하위 클래스에서 overriding할 것으로 예상되는 메소드를 메모리 낭비 없이 미리 호출 계획을 세워 두기 위해 작성한다.
  • 추상 클래스는 객체를 생성할 수 없다.
  • 추상 클래스를 상속 받은 하위 클래스는 추상 클래스가 아닌 경우 상위 클래스의 추상 메소드를 재정의 해야한다.
  • 추상 메소드가 없어도 추상 클래스로 작성할 수 있다. 
abstract class SortInt {
	private int[] value;
    
    protected abstract void sorting(); // 추상 메소드
    
    public void sort(int[] value) {
    	this.value = value;
        sorting();
    }
    
    // 배열의 길이
    protected int length() {
    	int n = -1;
        if(value != null) {
        	n = value.length;
        }
        return n;
    }
    
    // 두 정수 비교. final 메소드 - 하위클래스에서 재정의 불가
    protected final int compare(int i, int j) {
    	return value[i] - value [j];
    }
    
    // 배열의 두 요소 값을 서로 바꾸기
    protected final void swap(int i, int j) {
    	int t = value[i];
        value[i] = value[j];
        value[j] = t;
    }
}
class SelectionSort extends SortInt {
	@Override
	protected void sorting() {
		for(int i = 0; i < length() - 1 ; i++) {
			for(int j = i+1; j < length(); j++) {
				if(compare(i, j) > 0) {
					swap(i, j);
				}
			}
		}	
	}
}
class BubbleSort extends SortInt{
	@Override
	protected void sorting() {
		boolean flag = true;
		
		for(int i = 1; flag ; i++) {
			flag = false;
			for(int j = 1; j < length() - i; j++) {
				if(compare(j, j + 1) > 0) {
					swap(j, j+1);
					flag = true;
				}
			}
		}
		
	}
}

업캐스팅 = 어떠한 경우라도 가.

다운캐스팅 = 업캐스팅한 것만 가능!

package ex0723;

public class Ex05_ClassTypeCast {
	public static void main(String[] args) {
		Test5 t1 = new Test5();
		Test5 t2 = new Sample5();
		Test5 t3 = new Demo5();
		
		t1.disp(); // Test5의 print...
		// 재정의 하면 어떠한 경우라도 원래의 메소드로 돌아가지 않음!!
		t2.disp(); // Sample5의 print...
		t3.disp(); // Test5의 print...
		
		// Integer a=10;
		// Long b = a; // 컴오류
		// Long b = (Long)a; 컴오류. 상속관계에서만 캐스팅 가능. 형제는 남이다.
		
	}
}
class Test5 {
	public void print() {
		System.out.println("Test5의 print...");
	}
	
	public void disp() {
		// write(); 컴오류
		print();
	}
}

class Sample5 extends Test5{
	public void print() {
		System.out.println("Sample5의 print...");
	}
	
	public void write() {
		System.out.println("write...");
	}	
}

class Demo5 extends Test5 {
	public void sub() {
		System.out.println("sub...");
	}
}

'쌍용강북교육센터 > 7월' 카테고리의 다른 글

0726_Ex02_interface  (0) 2021.07.26
0726_Ex01_abstract : 추상 클래스  (0) 2021.07.26
0723_Ex04_ClassTypeCast  (0) 2021.07.23
0723_Ex03_ClassTypeCast : up-casting, down-casting  (0) 2021.07.23
0723_Ex02_override : 재정의  (0) 2021.07.23

+ Recent posts