'2019/11/18'에 해당되는 글 2건

728x90

이것이 자바다 유투브 강좌에 나온 내용중에서 인터페이스 부분을 정리해서 적어둔다.

https://www.youtube.com/watch?v=UPWiPIROG-k

 

 

인터페이스 선언

- 추상메서드의 집합

- 구현된 것이 전혀 없는 설계도

- 모든 멤버가 public 이라 생략 가능 (메서드는 public abstract, 상수는 public static final 생략 가능)

- 변수, 생성자를 가질 수 없다.

interface 인터페이스이름 {

    public abstract 메서드이름(매개변수목록);

}

 

인터페이스 구현 (→ 미완성 설계도 완성하기)

- 인터페이스에 정의된 추상 메서드를 완성시키는 것

class 클래스이름 implements 인터페이스이름 {

     // 인터페이스에 정의된 추상메서드를 모두 구현해야 한다.

}

- 만약 일부만 구현하는 경우, 클래스 앞에 abstract를 붙여야 한다.

 

특정한 Class 내에서만 사용하는 인터페이스를 정의한 걸 중첩 인터페이스라고 한다.

main 메서드에서 Button 클래스 객체를 생성하고 setOnClickListener() 메소드를 호출할 때 해당 인터페이스를 구현하는 자식 클래스로 값을 넘겨 준다. 그러면 다형성의 효과로 onClick() 메소드가 override한 결과로 나오게 된다.

 

public class Button {
    OnClickListener listener; // 중첩 인터페이스 타입으로 선언
   
    interface OnClickListener {
        void onClick(); // 추상 메소드
    }
   
    void setOnClickListener(OnClickListener listener) {
        this.listener = listener;
        // 외부에서 구현 객체를 받아서 필드에 저장한다.
    }
   
    void touch() {
        listener.onClick();
    }
   
}

import InterfaceEX.Button.OnClickListener;
public class CallListener implements OnClickListener {
    @Override
    public void onClick() {
        System.out.println("전화를 겁니다.");
    }
}

import InterfaceEX.Button.OnClickListener;
public class MessageListener implements OnClickListener {
    @Override
    public void onClick() {
        System.out.println("메시지를 보냅니다.");
    }
}

public class ButtonEx {

    public static void main(String[] args) {

        Button btn = new Button();
       
        btn.setOnClickListener(new CallListener()); // 내부 인터페이스 객체 생성
        btn.touch();
       
        btn.setOnClickListener(new MessageListener());
        btn.touch();

        Button.OnClickListener listener = new Button.OnClickListener() {
            @Override
            public void onClick() {
                System.out.println("사진을 찍습니다.");
            }
        };
        btn.setOnClickListener(listener);
        btn.touch();
       
        btn.setOnClickListener(new Button.OnClickListener() { // 익명 구현 객체
            // 익명 객체는 클래스를 상속하거나 인터페이스를 구현해야만 생성할 수 있다.
            // UI 이벤트 처리 객체나, 쓰레드 객체를 간편하게 생성할 목적으로 주로 사용한다.   
            // 익명 객체는 부모 타입 변수에 대입되므로 부모 타입에 선언된 것만 사용할 수 있다.
            // 외부에서는 익명 객체의 필드와 메소드에 접근할 수 없다.
            @Override // 부모 클래스(Button)의 메소드 재정의
            public void onClick() {
                System.out.println("이미지를 클릭합니다.");
            }
        });
        btn.touch();
    }
}

 

 

아래 코드는 자바의 정석 동영상 강좌를 듣고 구글링 여러 예제를 하나의 파일로 조합하여 작성한 것인다.

 

interface Printable {
    int x=10;
    void print(); // 추상메소드
}
 
interface Drawable {
    void draw(); // 추상메소드
    default void msg(){ // Java 1.8 이상에서 제공
        System.out.println("Drawable default method");
    }
}
 
interface Showable extends Printable {
    // 인터페이스 상속(Inheritance)
    void show(); // 추상메소드
}
 
class Parent {
    public void method2() {
        System.out.println("This is method2() in Parent Class");
    }
}
 
class Child extends Parent implements Printable, Drawable {
    @Override
    public void print() { // 인터페이스(추상 메소드) 구현
        System.out.println("Hello");
    }
 
    @Override
    public void draw() { // 인터페이스(추상 메소드) 구현
        System.out.println("drawing rectangle");
    }
}
 
class CustomDialog {
    // 특정한 Class 내에서만 사용하는 인터페이스를 정의한 걸 중첩 인터페이스라고 한다.
    interface CustomDialogListener {
        void onAgreeButtonClicked(String smsotp); // 추상 메소드
    }
 
    private CustomDialogListener customDialogListener;
    public void setCustomDialogListener(CustomDialogListener listener){
        customDialogListener = listener;
        // 외부에서 구현 객체를 받아서 변수에 저장한다.
    }
 
    String smsotp;
 
    public void Cick(){
        smsotp = "123456";
        customDialogListener.onAgreeButtonClicked(smsotp);
    }
}
 
public class Interface_EX implements Showable {
    @Override
    public void print() {
        System.out.println("print interface method implemented.");
    }
 
    @Override
    public void show() {
        System.out.println("show interface method implemented.");
    }
 
    public static void main(String[] args) {
 
        // 객체  생성 1
        Child child = new Child();
        child.print();
        child.draw();
        child.msg();
        child.method2();
 
        System.out.println(Printable.x);
 
        // 객체  생성 2
        Interface_EX interface_ex = new Interface_EX();
        interface_ex.print();
        interface_ex.show();
 
        // 객체  생성 3
        CustomDialog dialog = new CustomDialog();
        dialog.setCustomDialogListener(new CustomDialog.CustomDialogListener() { // 익명 구현 객체
            // 익명 객체는 클래스를 상속하거나 인터페이스를 구현해야만 생성할 수 있다.
            // 익명 객체는 부모 타입 변수에 대입되므로 부모 타입에 선언된 것만 사용할 수 있다.
            // 외부에서는 익명 객체의 변수와 메소드에 접근할 수 없다.
            @Override
            public void onAgreeButtonClicked(String smsotp) {
                System.out.println("customdialog result : "+smsotp);
            }
        });
        dialog.Cick();
 
    }
}
 

 

 

블로그 이미지

Link2Me

,
728x90

C언어 포인터를 학습하고 나서 swap 함수로 값을 넘기는 것과 주소를 넘기는 것을 비교해보면서 원하는 결과가 어떻게 도출되는지를 확인해볼 수 있다.


swap 함수와 swap_p함수를 같이 넣어서 call by value, call by reference 를 각각 처리하는 걸 비교해볼 수 있게 했다.


#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

void swap(int x, int y) { // int &x, int &y 로 변경해 보면 결과가 어떻게 나오는지 확인해보라.
    int tmp = x;
    x = y;
    y = tmp;

    printf("swap 함수 내 결과 : ");
    printf("x = %d, y = %d ", x, y);
    printf("&x = %p, &y = %p\n", &x, &y);


  

    // swap() 함수 내에서는 x, y 값이 변경 되었지만,
    // 정작 main() 함수에서는 a, b 값이 그대로 인 것을 확인할 수 있다
    // 오직 swap() 함수 내의 지역 변수에서만 유효함을 확인할 수 있다
}

void swap_p(int *x, int *y) { // 함수의 매개변수는 포인터 타입으로 선언
    int tmp = *x; // 역참조 연산자(*)를 사용하여 포인터가 가리키는 주소에 저장된 값을 tmp 에 저장
    *x = *y;
    *y = tmp; // tmp 를 포인터가 가리키는 주소에 저장된 값에 저장

    printf("swap 함수 내 결과 : ");
    printf("x = %d, y = %d ", *x, *y); // 값 출력
    printf("&x = %p, &y = %p\n", x, y); // 주소 출력


  

}

int main() {
    int a = 2;
    int b = 3;

    printf("swap 이전 값 출력 : ");
    printf("a = %d, b = %d ", a, b);
    printf("&a = %p, &b = %p\n", &a, &b);

    //scanf("%d%d", &a, &b);

    //swap(a, b); // 값을 넘겨준다(call-by-value)

    swap_p(&a, &b); // 주소를 넘겨준다.(call-by-reference)

    printf("swap 이후 값 출력 : ");
    printf("a = %d, b = %d ", a, b);
    printf("&a = %p, &b = %p\n", &a, &b);

    return 0;
}


값에 의한 전달(call by value)
값에 의한 전달 방법은 인수로 전달되는 변수가 가지고 있는 값을 함수 내의 매개변수에 복사하는 방식이다.
이렇게 복사된 값으로 초기화된 매개변수는 인수로 전달된 변수와는 완전히 별개의 변수가 된다.
따라서 함수 내에서의 매개변수 조작은 인수로 전달되는 변수에 아무런 영향을 미치지 않다.


참조에 의한 전달(call by reference)
참조에 의한 전달 방법은 인수로 전달된 변수의 값을 복사하는 것이 아닌, 원본 데이터를 직접 전달하는 것이다.
C언어에서는 이러한 작업을 포인터를 사용하여 인수로 전달된 변수의 주소값을 전달한다.
하지만 C++에서는 이러한 작업을 참조자(reference)를 사용하여 전달할 수 있다.



Java

Java는 기본형(primitive) 데이터 외에는 모두 참조형(reference) 데이터다.

기본형은 call by value 이고 객체는 call by reference 이다.


구글링을 해보면 Java 는 call by value 다, call by reference 다 의견이 분분하다.

https://www.tutorialspoint.com/Call-by-value-and-Call-by-reference-in-Java 를 참조하면 도움이 될 것 같다.


public class Tester {

    public static void main(String[] args) {
        int a = 30;
        int b = 45;
        System.out.println("Before swapping, a = " + a + ", b = " + b);

        swap(a, b);
       
        System.out.println("\nAfter swapping, a = " + a + ", b = " + b);
    }

    public static void swap(int x, int y) {
        System.out.println("\nBefore swapping(Inside), x = " + x + ", y = " + y);

        int tmp = x;
        x = y;
        y = tmp;
        System.out.println("After swapping(Inside), x = " + x + ", y = " + y);
    }

}

실행 결과 ==> 원하던 결과가 아님을 알 수 있다. swap 메소드에 넘기는 것이 value 이기 때문이다.

Before swapping, a = 30, b = 45
Before swapping(Inside), x = 30, y = 45
After swapping(Inside), x = 45, y = 30
After swapping, a = 30, b = 45


public class Tester {

    public static void main(String[] args) {
        IntWrapper a = new IntWrapper(30);
        IntWrapper b = new IntWrapper(45);


        System.out.println("Before swapping, a = " + a.value + ", b = " + b.value);

        swap(a, b);

        System.out.println("After swapping, a = " + a.value + ", b = " + b.value);
    }

    public static void swap(IntWrapper x, IntWrapper y) {
        System.out.println("Before swapping(Inside), x = " + x.value + ", y = " + y.value);

        int tmp = x.value;
        x.value = y.value;
        y.value = tmp;
        System.out.println("After swapping(Inside), x = " + x.value + ", y = " + y.value);
    }
}

class IntWrapper {
    public int value;

    public IntWrapper(int value) {
        this.value = value;
    }
}

실행 결과 ==> reference 로 받은 다음, 그 내부 변수를 서로 변경하는 방법으로 처리

Before swapping, a = 30, b = 45
Before swapping(Inside), x = 30, y = 45
After swapping(Inside), x = 45, y = 30
After swapping, a = 45, b = 30

블로그 이미지

Link2Me

,