[Java] Overloading vs Overriding

정지은·2022년 11월 17일
0

스프링(+자바)

목록 보기
2/5
post-custom-banner

"그래서 오버로딩이랑 오버라이딩이 뭐가 다른데?"
단순 암기로 적용해 코딩을 하고는 있지만, 막상 질문을 받으면 머리속이 멍해진다. 심지어 단어도 비슷해 더 헷갈린다. 그래서 아예 정리해 두기로 했다.


0. 시작하기 전 : 상속이란?

가장 눈에 띄는 차이라 하면, 오버라이딩은 상속 관계에서 사용하지만 오버로딩은 그렇지 않다는 점이겠다. 때문에 둘의 차이를 설명하기 위해서는 자바의 상속 개념에 대해 알고 있어야 한다.

자바에서는 한 클래스가 다른 클래스의 필드와 메소드를 가져와 자기 것처럼 쓸 수 있다. 이것을 상속이라고 하며, 메소드를 빌려준 클래스를 부모 클래스(상위 객체), 메소드를 가져온 클래스를 자식 클래스(하위 객체)라고 한다.

상속 시, 하위 객체는 상위 객체의 특징(메소드, 변수 등)을 물려받게 된다. 이 때, 상위 객체의 특징을 '새롭게 구현'하는가, '그대로 사용'하는가에 따라서 상속의 형태가 갈리게 된다.

  • extends
    부모에서 선언/정의를 모두하며, 자식은 오버라이딩 할 필요 없이 부모의 선언과 정의를 그대로 사용할 수 있다(부모 객체에 A라는 메소드가 있었다면, 그것을 상속받은 자식 객체에서 별다른 재정의 없이 A를 바로 호출 가능.)
  • implements
    부모 객체는 선언만 하며, 정의는 반드시 자식이 오버라이딩해서 사용한다.
    부모 객체가 정의한 메소드/변수를 사용하는 extends와 달리, implements는 인터페이스 객체를 상속받아 자식이 그 내용을 정의한다.

  • abstract
    extends와 interface의 기능을 합쳤다.
    기본적으로는 extends로 동작하지만 추상 메소드도 사용가능하다.

public interface NoticeService {
	//CRUD Create, Read, Update, Delete
	void notice_insert(NoticeVO vo);	//공지글 저장
	List<NoticeVO> notice_list();	//공지글 목록 조회
	NoticeVO notice_detail(int id); //공지글 상세 조회
	void notice_update(NoticeVO vo); //공지글 변경 저장
	void notice_delete(int id); //공지글 삭제
	void notice_read(int id); //조회수 증가 처리
	NoticePage notice_list(NoticePage page);	//페이지 처리 된 공지글 목록 조회
	void notice_reply_insert(NoticeVO vo); //답글 저장
}

// NoticeService.java

@Service
public class NoticeServiceImpl implements NoticeService {
	@Autowired private NoticeDAO dao;
	
	@Override
	public void notice_insert(NoticeVO vo) {
		dao.notice_insert(vo);
	}

	@Override
	public List<NoticeVO> notice_list() {
		// TODO Auto-generated method stub
		return dao.notice_list();
	}

	@Override
	public NoticeVO notice_detail(int id) {
		return dao.notice_detail(id);
	}

	@Override
	public void notice_update(NoticeVO vo) {
		dao.notice_update(vo);
	}

	@Override
	public void notice_delete(int id) {
		dao.notice_delete(id);
		
	}
	
	@Override
	public void notice_read(int id) {
		dao.notice_read(id);
	}
	
	@Override
	public NoticePage notice_list(NoticePage page) {
		return dao.notice_list(page);
	}

	@Override
	public void notice_reply_insert(NoticeVO vo) {
		dao.notice_reply_insert(vo);
	}
	
}

//NoticeServiceImpl.java


1. 오버로딩Overloading

일반적으로 동일한 이름의 메소드는 실행 시 오류가 발생하기 때문에 함께 존재할 수 없다. 코드를 작성하면서 종종 저지르는 실수이기도 하다. 하지만 오버로딩은 동일한 이름의 메소드를 작성할 수 있게 한다.

오버로딩을 위한 조건

  1. 메소드의 이름이 같을 것
  2. 매개변수의 개수, 타입이 다를 것
    (+) 매개변수가 동일하고 반환 타입만이 다른 경우는 오버로딩이라고 치지 않는다.

만약 회원 정보 등록을 위한 클래스를 작성하는 중에, 매개변수로 주어진 정보의 개수와 종류가 각자 다르다면 어떻게 해야 할까? 각 경우에 맞춰 메소드를 새로 이름지어 따로 호출하는것은 아무래도 비효율적이다. 오버로딩을 사용하면 이름만 있는 회원도, 전화번호만 있는 회원도, 기타등등도 모두 메소드명 하나로 해결할 수 있다.

@Service
public class NoticeServiceImpl implements NoticeService {
	@Autowired private NoticeDAO dao;
	
	@Override
	public List<NoticeVO> notice_list() {
		// TODO Auto-generated method stub
		return dao.notice_list();
	}
	@Override
	public NoticePage notice_list(NoticePage page) {
		return dao.notice_list(page);
	}
	
}

// NoticePage를 매개변수로 한 호출도, 매개변수가 없는 호출도
// 모두 notice_list로 처리가능하다.
// 리턴 타입이 다른 것은 오버로딩의 조건이 아니다!


2. 오버라이딩Overriding

지금껏 예시로 붙여 두었던 코드를 보자. @Override라는 태그가 붙어 있다. 이 메소드들이 전부 오버라이딩 된 상태라는 의미이다. 예시 코드는 인터페이스에서 메소드 이름과 매개변수, 반환 타입만을 설정하고, 그것을 상속받은 클래스에서 비로소 내용을 정의하고 있다.

즉, 오버라이딩이란 부모 클래스가 가지고 있는 메서드를 자식 클래스가 재정의해서 사용하는 것이라 할 수 있다. 대부분의 IDE에서는 클래스를 상속하면 친절하게 오버라이딩 메소드가 자동으로 생성된다. 여기서 해당 클래스의 목적에 맞게 입맛대로 내용을 작성하면 된다.

만약 부모 클래스의 메소드에 이미 정의된 내용이 있을 때 오버라이딩을 한다면 어떻게 될까? 부모 클래스의 메소드 내용은 무시하고, 자식 클래스의 오버라이딩된 메소드만이 실행된다. 부모 클래스의 메소드 내용을 실행하고 싶다면 super 예약어를 사용한다.

public interface NoticeService {

	void notice_insert(NoticeVO vo);	//공지글 저장

}

// NoticeService.java
@Service
public class NoticeServiceImpl implements NoticeService {
	@Autowired private NoticeDAO dao;
	
	@Override
	public void notice_insert(NoticeVO vo) {
		dao.notice_insert(vo);
	}
	
}

//NoticeServiceImpl.java
profile
Steady!
post-custom-banner

0개의 댓글