본문 바로가기

Programming language/Java

Java - 13 [Generic, 인터페이스]

Generic(제네릭)

public class Box<T> {
    private T something;

    public void set(T object) { 
        this.something = object;
    }

    public T get() {
        return something;
    }
}

- 위 코드에서 <T> 이렇게 꺽쇠 표시 안에 담긴 것을 '타입 파라미터'라고 한다.

- 이러한 타입파라미터를 인수로 받는 클래스를 '제네릭(Generic) 클래스' 라고 한다.

 

이러한 제네릭 클래스로 인스턴스를 선언할 때 T 라는 타입파라미터를 바꿔준다면

 

Box<String> box = new Box<>();
public class Box<String> {
    private String something;

    public void set(String object) {
        this.something = object;
    }

    public String get() {
        return this.something;
    }
}

- 해당 인스턴스의 구조가 이렇게 바뀐다고 생각하면 된다.

 

타입제한

public class PhoneBox extends Box<Phone> {
    public void handsFreeCall(String numberString) {
        object.call(numberString);
    }
}

- 위구조에서 PhoneBox는 Box<Phone>이라는 제네릭 클래스를 상속받는다.

즉, 박스에서 Phone이라는 클래스 타입을 받아서 확장한 것이니,  결국에는 Phone이라는 클래스 타입만

받겠다는 이야기이다. 즉, 타입제한을 이렇게 건것인데 다른형태로도 걸수 있다.

public class PhoneBox<T extends Phone> extends Box<T> {
    public void handsFreeCall(String numberString) {
        object.call(numberString);
    }
}

- 위코드에서 <T extends Phone> 이부분은 Phone 클래스의 자식클래스만 확장을 받겠다는 뜻 입니다.

이렇게하면 T라는 제네릭클래스라는 클래스를 받고 T라는 타입파라미터로 타입제한을 자식클래스 형태로 받을수 있습니다.

 

- 사실 위코드와 별다른 차이는 못느끼겠다.

 

인터페이스(Interface)

- 메소드만 명시되어있는 부모 클래스라고 생각하면된다.

다만 변수, 메소드를 가질수 없고 

빈 메소드만 허용된다.

 

따라서 인터페이스를 ArrayList에도 넣을 수 있다.

예를 들어 이러한 인터페이스를 따르겠다고 명시한 클래스는 인터페이스에 적힌 

메소드들을 구현하지 않으면 에러가 난다.

 

인터페이스 안에는 메소드를 넣을수 있는데 구현할 수는 없다.

 

인터페이스는 class가 아니라 인터페이스라는 구조이다.

public interface Shape {
    double getArea();
    double getPerimeter();
}

 

따라서 이렇게 타입을 선언하고 메소드를 선언하는데 메소드는 접근제어자를 명시하지 않는다.

기본적으로 public이기 때문이다. 따라서 자료형만 명시하고 중괄호를 열지않고 닫아준다.

 

public class Circle implements Shape {
    public static final double PI = Math.PI;
    private final double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double getArea() {
        return radius * radius * PI;
    }

    @Override
    public double getPerimeter() {
        return radius * 2 * PI;
    }
}

- 이러한 형태로 Shape 인터페이스에 해당하는 메소드들을 모두 구현해야한다.

 

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<Shape> shapes = new ArrayList<>();
        shapes.add(new Circle(2));
        shapes.add(new Rectangle(2, 3));

        for (Shape shape: shapes) {
            System.out.println("Area: " +shape.getArea());
        }
    }
}

이렇게 ArrayList 타입에도 넣을수 있고, 부모클래스의 메소드를 사용하는 것처럼 사용이 가능하다.