김영한님의 스프링 강의를 들으면서 궁금했던 것들, 자바 문법을 처음 접하면서 신기하거나 궁금했던 것들에 대해서 정리해 보려고 한다.
우선 김영한님의 강의를 듣다보면, 객체지향적인 설계에 초점을 맞추시는 것을 볼 수 있다.
그에 따라서 코드 또한 객체지향적으로 설계를 하시면서, 응집도와 결합도를 중요시 다루는 것을 볼 수 있다.
과연 그렇다면 응집도와 결합도는 무엇일까?
여기서 말하는 모듈은 기능별로 나눠진 것을 모듈이라고 하며, 이렇게 소프트웨어를 각 기능(모듈)로 나누는 것을 모듈화라고 한다.
이 정도로 응집도와 결합도에 대한 배경지식을 정리하였다.
강의를 듣다보면 Repository
나 Service
를 Interface를 구현시키거나 추상 클래스를 상속받아 사용하는 경우가 많은데, 왜 그렇게 하는 것이며 둘이 무슨 차이가 있는지 조금 알아보려고 한다.
abstract
와 final
키워드는 동시에 사용 불가능하다. 클래스 내에 단 한개의 추상메소드(구현되어 있지 않은 abstract 메소드)가 존재한다면 반드시 abstract class로 선언해야 한다.public abstract class AbstractClass {
public abstract void exampleMethod();
public void normalMethod(){
System.out.println("일반적인 메소드 입니다.");
}
}
public class ExClass extends Abstractclass {
@Override
public void exampleMethod(){
System.out.println("추상 클래스의 추상 메소드를 구현했습니다.");
}
}
그래서 추상클래스와 인터페이스는 사용 용도가 구분이 된다. 추상클래스는 대상의 속성을, 인터페이스는 대상의 기능을 표현할 때 사용하는 것으로 말이다.
추상클래스는 공통된 개념을 표현할 때 쓴다고 한다. 그러니까 예를 들면 말, 사자, 호랑이는 피부색이 있고 이름이 있고 달리는 동물들이니까, 동물이라는 속성을 추상 클래스로 만들고 달린다는 것을 추상 메소드로 만든다음, 말이라는 객체에 상속시켜서 구현하면 객체의 재사용성이 높아지고 표현하는 것이 더 명확해진다. 말은 달리는 속도가 빠르고 강아지느 느리니까, 달리기를 구현할 때 이 둘의 차이를 둘 수가 있다.
인터페이스는 구성하는 요소들이 자주 바뀔 때 사용하면 유용하다고 한다. 메소드들의 내용은 몰라도 결과값은 미리 알 수 있으니까, 메소드 형태만 서로 공유하여 구현하는 상황일 때 적합하다고 한다.
100% 이해는 안되지만, 어느정도 구분이 가는 것 같다.
이것도 항상 쓸때마다 제대로 알고 쓰는게 아니어서 궁금했다. 제대로 알고 써보자.
먼저 final
키워드는 상수, 메소드, 클래스 이렇게 3가지 경우에 사용이 가능하다고 한다.
final int ex;
ex = 3;
ex = 5; // 오류
final은 이처럼 값을 바꾸고 싶지 않을 때 사용하는 것이라고 이해를 하면 되겠다.
상수에 선언하면 상수의 값을 바꿀 수 없고, 메소드에 선언하면 오버라이딩을 할 수 없고, 클래스에 선언하면 상속을 할 수 없어 내용을 변경할 수 없는 것이다.
그렇다면 static final은 무엇일까? 앞서 사용한 final 개념에 static을 추가한 것이다.
즉, 객체마다 존재하는 인스턴스가 아니라, 클래스에 존재하는 단 하나의 상수이다.
그러니까, 클래스를 여러개 선언해도 클래스에 존재하는 단 하나의 상수이므로, 값이 당연히 변경이 안될 것이며, 선언과 동시에 무조건 초기화를 해줘야 하는 클래스 상수인 것이다.
그러니까..음..final a = 3
을 모든 클래스 마다 해준다면 static final int a = 3
이 되는 것이 되는 것일까 라는 의문이 든다.
아마도 그게 맞는 것이라고 생각이 드는게, 실제로 우리가 lombok을 사용하여 private static final 객체를 private final 에 @RequiredArgsConstructor
를 사용하는 방식으로 바꿔서 사용하는 것을 보면, 어느정도 맞는 것 같다.