먹었으면 뇌를 쓰자

[해결완료] 디폴트 메소드와 스태틱 메소드의 차이는 뭘까? 본문

JAVA/개념

[해결완료] 디폴트 메소드와 스태틱 메소드의 차이는 뭘까?

뇌이비 2022. 12. 17. 09:06

(22.12.17 작성)

아래 코드에서 Predator 인터페이스에 디폴트 메소드 printFood()와 스태틱 메소드 speed()를 정의했다.

둘 다 구현체(Tiger, Lion)에 명시하지 않고 메인 메소드에서 호출하면 잘 작동되는데

그렇다면 둘의 차이는 무엇일까?

 

 

interface Predator{
	String getFood();
	
	default void printFood() {
		System.out.printf("my food is %s\n", getFood());
	}
		
        
    int LEG_COUNT = 4;  // 앞에 public static final이 생략된 인터페이스 상수
        
	static int speed() { // 메인 메소드 호출은 Predator.speed()
		return LEG_COUNT * 30; 
	}
}


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

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

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

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

}


public class coding {		
	public static void main(String[] args) {
		
		ZooKeeper zooKeeper = new ZooKeeper();
		Tiger tiger = new Tiger();
		Lion lion = new Lion();
		
		zooKeeper.feed(tiger); // feed apple
		tiger.printFood();	// my food is apple			
		System.out.println("the speed is "+ Predator.speed()); // the speed is 120
		
		zooKeeper.feed(lion); // feed banana
		lion.printFood(); // my food is banana		
		System.out.println("the speed is "+ Predator.speed()); // the speed is 120
			
        
        
	}
}

 

 

 

(22.12.18 해결)

둘의 차이는 다음과 같다.

 

 

디폴트 메소드

원래 인터페이스에 정의하는 메소드는 형식만 존재한다.

메소드의 작동 내용은 인터페이스를 구현하는 클래스들이 각자 명시해야 한다.

 

그런데 이렇게 하면 클래스를 추가할 때마다 메소드 내용을 계속 써야 한다. 

디폴트 메소드는 인터페이스에 형식과 내용을 모두 명시해서 이런 불편을 없애준다. 

 

아래 코드에는 Predator 인터페이스에 디폴트 메소드 printFood()를 만들었다.

 

 

interface Predator{
	String getFood();
	
	default void printFood() {
		System.out.printf("my food is %s\n", getFood());
	}
		
 	//... 

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

	// ...

public class coding {		
	public static void main(String[] args) {
		
		Tiger tiger = new Tiger();

		tiger.printFood();	// my food is apple ★				
        
	}
}

 

 

위와 같이 Tiger 클래스에는 따로 printFood() 메소드를 명시하지 않았지만, 

메인 메소드에서 Tiger 클래스의 객체인 tiger에서 tiger.printFood() 메소드를 호출할 수 있다.

 

Predator 인터페이스를 구현한 lion, bear, eagle ... 등등의 객체는 모두

lion.printFood(), bear.printFood(), eagle.printFood() 를 호출할 수 있다. 오버라이딩도 가능하다.

 

 

 

 

스태틱 메소드

스태틱 메소드에 대해 이해하려면 먼저 static의 의미를 알아야 한다. 

 

static은 '인스턴스(복사본)를 만들지 않고 하나의 데이터를 공유하는 개념'이다. 

인스턴스를 만들어 여러 개의 데이터를 만드는 작업과 반대인 것이다. 

 

어떤 인스턴스를 만들어도 동일한 값이 사용될 때 static을 붙여 메모리를 절약할 수 있다.

(값이 변경되지 않기를 원한다면 final static으로 쓴다)

 

class HouseLee {
	// String lastname = "이"; <- lee1의 lastname, lee2의 lastname, lee3의 lastname...
    static String lastname = "이"; // <- 하나의 lastname (lee1, lee2, lee3 ... 공유)
}

public class Sample {
    public static void main(String[] args) {
        HouseLee lee1 = new HouseLee();
        HouseLee lee2 = new HouseLee();
    }
}

코드 참고 : 점프 투 자바 (wikidocs.net/228)

 

 

그렇다면 스태틱 메소드는 하나의 변하지 않는 메소드를 공유하는 개념이라 할 수 있다. 

'공유'라는 차원에서 디폴트 메소드와 헷갈리는 것 같다.

 

 

 

(인터페이스) 디폴트 메소드&스태틱 메소드의 공통점

 

-> 인터페이스에 메소드 내용과 형식을 모두 적는다. 

-> 구현체(클래스)에 메소드를 정의하지 않아도 메인 메소드에서 객체에 바로 호출할 수 있다.

 

 

 

디폴트 메소드의 특징 

 

-> 모든 구현체가 공통으로 디폴트 메소드를 호출할 수 있도록 하는 것이 주 목적이다.

ex)  동물들은 '먹이를 먹는다'. 단, 동물별로 먹이는 다르다.

 

-> 각각의 구현체는 디폴트 메소드를 오버라이딩할 수 있다.

-> 디폴트 메소드를 호출한 구현체 인스턴스별로 (메소드에 대한) 새로운 메모리 주소가 할당된다.

 

 

 

스태틱 메소드의 특징

 

-> 모든 구현체가 사용할 수 있는, 변하지 않는 내용의 메소드를 만드는 것이 주 목적이다.

ex) 동물들은 '다리가 4개다.'  

 

-> 스태틱 메소드를 호출한 구현체 인스턴스별로 (메소드에 대한) 동일한 메모리 주소를 사용한다. 

 

 

Comments