[Java 스터디] 다형성 마무리

🐧코딩하는 애기 펭귄·2023년 5월 30일
1

sscc Java 스터디

목록 보기
10/10
post-thumbnail

개요

지난 번 포스팅에서 다형성이란 무엇인지 살짝 찍먹해보았는데,

이번 포스팅에서는 다형성을 구현하는 방법을 정리하는 시간을 가져보도록 하자. 추가적으로 그 외 여러가지 자잘한 문법들을 소개하며 마무리하겠다.

cf) 이 글은 2023년 5월 23일에 진행됐던 sscc 자바 스터디 6주차 스터디 내용을 정리한 글입니다.

인터페이스

다형성을 구현하는 여러가지 방법 중에 인터페이스가 있다.

인터페이스를 만드는 이유는 설계, 개발, 유지보수 세 단계 중에서 가장 오랜 기간동안 해야 하는 유지보수의 편의성을 위함이 제일 크다.

기본적으로 추상 클래스와 사용하는 방법이 비슷하다.
클래스 타입이 아닌 interface 타입으로 명시해서 정의해야 하고, 내부적으로는 메소드 선언문만을 명시하는 것이 원칙이다. (자바가 업그레이드 되면서 인터페이스 내부에서도 필드 변수나 메소드 정의가 가능해졌다.)

메소드를 구현하는 것은 해당 인터페이스를 implements 하는 클래스의 몫이다. 이 클래스들은 반드시 해당 인터페이스에 선언된 메소드들을 구현해야 한다.

점프 투 자바에 나온 예시를 같이 보면서 더 자세히 알아보자.

동물원 사육사 예제

난 동물원의 사육사이다. 육식동물이 들어오면 난 먹이를 던져준다. 호랑이가 오면 사과를 던져준다. 사자가 오면 바나나를 던져준다.
-> 이 상황을 코드로 만든다고 생각해보자.

class Animal {
    String name;

    void setName(String name) {
        this.name = name;
    }
}

class Tiger extends Animal {

}

class  Lion extends Animal {

}

class ZooKeeper {
    void feed(Tiger tiger) {
        System.out.println("feed apple");
    }

    void feed(Lion lion) {
        System.out.println("feed banana");
    }
}

public class Exercise {
    public static void main(String[] args) {
        ZooKeeper zooKeeper = new ZooKeeper();
        Tiger tiger = new Tiger();
        Lion lion = new Lion();
        zooKeeper.feed(tiger);
        zooKeeper.feed(lion);
    }
}

이 코드에서는 ZooKeeper 클래스에서 매개변수가 tiger와 lion일 때를 고려해 feed 메소드를 오버로딩한 상황이다.

하지만 동물이 점점 늘어난다면?
동물이 하나 늘어날 때마다 feed 메소드를 추가 해야하므로 굉장히 비효율적인 코드가 된다.

-> 이럴 때 인터페이스를 이용해서 해결이 가능하다.

예제 코드에 인터페이스 적용

클래스 파일이 아닌 인터페이스 파일을 하나 만들고 Predator 라는 인터페이스를 정의한다.

인터페이스에는 껍데기만 정의하고 클래스에서 이 메소드를 구현한다.
-> 각각의 클래스에서 여러가지 모양으로 구현할 수 있다는 뜻

아래는 Predator 인터페이스를 implements 하도록 수정된 코드이다.

// 수정된 코드

// ...

class Tiger extends Animal implements Predator {
    public String getFood() {
        return "apple";
    }
}

class  Lion extends Animal implements Predator{
    public String getFood() {
        return "banana";
    }
}

class ZooKeeper {
    public void feed(Predator predator) {
        System.out.println(predator.getFood());
    }
}

// ...

인터페이스 구현으로 인해 얻을 수 있는 장점

  1. 추가가 편해짐. ex) 다른 동물 등
  2. 객체간의 관계가 느슨해짐! (부모 관계가 아니기 때문)

결론적으로 유지보수가 용이해진다는 이점을 얻을 수 있다.

번외) 상속 관계로 구현

사실 위 예제는 꼭 인터페이스를 사용하지 않고, 우리가 전에 배웠던 상속을 이용해서도 구현이 가능하다.

아래는 추상 클래스로 구현한 예제 코드이다.

abstract class Animal {
    String name;

    void setName(String name) {
        this.name = name;
    }

    abstract String getFood();
}

class Tiger extends Animal {
    public String getFood() {
        return "apple";
    }
}

class  Lion extends Animal {
    public String getFood() {
        return "banana";
    }
}

class ZooKeeper {
    public void feed(Animal animal) {
        System.out.println(animal.getFood());
    }
}

상속으로 구현하는 것과 인터페이스로 구현하는 것의 차이가 뭘까?

-> 상속은 상속을 받은 클래스가 반드시 오버라이드 해야 하는 것은 아니다. But, 인터페이스를 implements 하면 반드시 메소드를 구현해야 한다.
-> 때문에 큰 프로젝트에서 분업할 때 인터페이스를 사용하면 실수를 줄일 수 있게 된다.

상황에 맞게 고르자.


그 외 여러가지

static

static 멤버

일반적인 멤버들은 객체마다 각각 생성되지만, static 멤버는 클래스당 하나만 생성된다. 때문에 클래스 멤버라고도 부른다.

객체를 생성하지 않고도 바로 사용 가능하기 때문에
객체가 아니라 클래스의 성격으로 호출, 조작해야 할 때 static을 사용한다.

정리하면 다음과 같다.

  • 공간적 특성 - static 멤버들은 클래스 당 하나만 생성
  • 시간적 특성 - static 멤버들은 클래스가 로딩될 때 공간 할당.
  • 공유의 특성 - static 멤버들은 동일한 클래스의 모든 객체에 의해 공유

static 활용

static을 사용하는 경우는 일반적으로 2가지다.

  1. 전역변수나 전역 함수를 만들 때 - java.lang.Math 클래스가 대표적인 예. 내부를 뜯어보면 모든 필드와 메소드가 public static으로 선언되어 있다. 때문에 다른 모든 클래스에서 사용할 수 있다.
  2. 공유 멤버를 작성할 때 - 해당 클래스로 생성된 모든 객체가 공통적으로 공유해야 되는 특성이 있을 때 static을 사용한다.

main 함수의 비밀...

main 함수 앞에 붙는 수식어들을 다시 상기시켜 보자.

public class Sample {
	public static void main(String[] args) {
    ...
    }
}

main 함수 앞에도 static이 붙어있는 모습을 확인할 수 있다.

이는 Sample 객체를 생성하지 않고도 JVM이 main 함수를 사용하기 위함이다.


package

폴더와 같은 개념이다.

서로 다른 폴더 안에 같은 이름의 파일을 넣을 수 있는 것도 동일하다.

패키지를 만들고, 그 안에 클래스를 만들면 인텔리제이가 알아서 첫 줄에 추가해준다.
Package 선언문은 반드시 소스코드의 첫 줄에 있어야 한다.

패키지 내부의 서브패키지에 접근할 땐 .(점)으로 구분한다.

다른 패키지에 있는 클래스를 사용하려면 import 해줘야 한다.

그동안 ArrayList나 Scanner 등 import문 쓰던 거 전부 Java가 기본으로 만들어둔 패키지 안에 있던 클래스들을 import 해서 사용한 것이다.


오늘은 이렇게 인터페이스와 static, package에 대해서 학습해보았다. 며칠 전에 본 topcit 평가에서 인터페이스와 추상 클래스의 차이를 물어보는 문제가 있었는데 공부를 안 하고 본 지라 뇌피셜로 적어서 냈다...

인터페이스는 팀 프로젝트를 진행할 때 굉장히 많이 사용하는 중요한 개념이니 잘 알아두도록 하자.

0개의 댓글

관련 채용 정보