[F-Lab 모각코 페이백 8일차] 얕은 복사, 깊은 복사, 추상클래스와 인터페이스 차이점
오늘 학습 계획
- 팀코칭 질문으로 학습
TIL
- 얕은 복사
- 깊은 복사
- 추상클래스와 인터페이스 차이점
- 원시 타입(primitive type)과 참조 타입(reference type)
얕은 복사(Shallow Copy)
얕은 복사(Shallow Copy): 얕은 복사를 하면 원본 객체의 필드 값이 복사본에 그대로 복사됩니다. 원시 타입의 필드에 대해서는 문제가 없지만, 참조 타입의 필드에 대해서는 원본 객체와 복사본이 같은 객체를 참조하게 됩니다. 즉, 복사본에서 참조 타입의 멤버를 변경하면 원본 객체의 해당 멤버도 변경되고, 반대로 원본에서 변경하면 복사본에 영향을 미치게 됩니다.
이해가 잘 안되어서 좀 더 알아보니
얕은 복사(Shallow Copy)"는 원본 객체의 필드 값을 복사본에 그대로 복사합니다. 원시 타입의 필드(예: int, float, boolean 등)는 그 값 자체가 복사되므로, 이들 필드에 대해서는 복사본과 원본이 완전히 독립적입니다.
하지만, 참조 타입의 필드(예: 객체, 배열 등)에 대해서는 얕은 복사가 "참조"를 복사합니다. 즉, 복사본의 해당 필드는 원본의 해당 필드가 참조하는 것과 같은 객체를 가리키게 됩니다. 따라서 복사본에서 이 참조를 통해 객체를 변경하면, 원본 객체에도 그 변경이 반영됩니다. 반대로 원본에서 변경하면 복사본에 영향이 미칩니다.
리눅스의 하드 링크와 비슷한 개념이라고 볼 수 있습니다. 하드 링크는 파일 시스템에서 두 개의 파일 이름이 같은 파일 내용을 가리키는 것과 같이, 얕은 복사에서 두 객체의 참조 필드가 같은 객체를 가리키게 됩니다.
이처럼 얕은 복사는 "복사된 것처럼" 보일 수 있지만, 실제로는 원본과 복사본이 일부 데이터를 공유하고 있습니다. 이는 상황에 따라 원하는 결과를 얻지 못하게 하거나 예상치 못한 부작용을 초래할 수 있으므로 사용할 때 주의가 필요합니다.
설명을 읽다가 참조 개념이 이해가 안되었다. 나는 메모리 주소 값을 스트링이나 인트 등의 타입으로 저장 하는 줄 알았는데
레퍼런스 참조 변수는 객체의 메모리 주소를 가리키는 변수라고 한다.
즉 메모리 주소 자체를 저장하지는 않고 그 메모리 주소에 해당하는 위치를 가리키는 것이라고 한다.
따라서 레퍼런스 참조 변수자체가 가리키는 의미를 담고 있다고 한다. 포인터역활이라고 생각하면 이해하기 쉬우 실 것 같기도 하다.
자바에서 원시 타입(primitive type)과 참조 타입(reference type)의 변수는 다르게 동작합니다:
- 원시 타입의 변수: 이 변수들은 실제 값을 직접 저장합니다. 이 타입에는 int, char, float, boolean 등이 있습니다. 예를 들어, int x = 10;에서 x는 원시 타입 변수로, 실제 정수 값을 저장하고 있습니다.
- 참조 타입의 변수: 이 변수들은 객체를 가리키는 참조를 저장합니다. 참조 타입에는 클래스 타입, 인터페이스 타입, 배열 타입이 포함됩니다. 예를 들어, String s = new String("Hello");에서 s는 참조 변수로, "Hello" 문자열 객체를 가리키는 참조를 저장하고 있습니다.
참조 변수를 다른 참조 변수에 할당하면, 두 변수는 같은 객체를 가리키게 됩니다. 즉, 한 변수를 통해 객체를 변경하면, 다른 변수를 통해 그 변경사항을 볼 수 있습니다. 이것은 얕은 복사(Shallow Copy)의 원리와도 일치합니다.
깊은 복사(Deep Copy)
- 깊은 복사(Deep Copy): 깊은 복사는 원본 객체의 모든 필드를 복사하지만, 참조 타입의 멤버에 대해서는 새로운 객체를 생성하여 그 객체의 값까지 복사합니다. 이로 인해 원본 객체와 복사본은 완전히 독립적이게 됩니다. 복사본에서 참조 타입의 멤버를 변경하더라도 원본 객체에는 아무런 영향이 없습니다.
깊은 복사를 하면 객체를 하나더 만들고 그곳에 원본 객체의 값을 복사하는 방식이다.
따라서 원본이 변경되더라도 깊은 복사로 생성한 객체는 유지가 되며 값의 변동도 없다.
내가 알고 있는 어릴적 부터 알고 있던 윈도우즈 파일 시스템의 복사의 의미와 같다고 생각한다.
윈도우즈 파일복사는 이름만 다르고 완전 같은 파일을 하나 더 만든다.
프로그래밍의 부분에선 얕은 복사와 깊은 복사 둘다 목적이 다르고 활용도 다르다고 생각한다.
아직 두 개념을 정확히 알고 구분해서 쓴적은 없어서 실제 사용과 활용은 어떻게 될지 잘 예상이 되지는 않지만
복사할 경우가 생긴다면 이 두 개념을 염두에 두고 개발해야겠다는 생각은 들었다.
추상 클래스(Abstract Class)
- 추상 클래스는 다른 클래스에서 상속 받아 사용할 수 있습니다. abstract 키워드를 사용하여 정의됩니다.
- 추상 클래스에는 추상 메서드(구현이 없는 메서드)뿐만 아니라 일반 메서드(구현이 있는 메서드)도 포함할 수 있습니다.
- 추상 클래스를 상속받는 클래스는 추상 클래스에서 정의한 추상 메서드를 모두 구현해야 합니다.
- 추상 클래스는 생성자를 가질 수 있고, 이를 통해 필드를 초기화할 수 있습니다.
- 상속을 통해 코드를 공유하므로, 상태(필드)와 동작(메서드)를 모두 가질 수 있습니다.
인터페이스(Interface)
- 인터페이스는 클래스가 구현할 수 있으며, interface 키워드를 사용하여 정의됩니다.
- 인터페이스는 일반적으로 모든 메서드가 추상 메서드입니다. 그러나 Java 8부터는 디폴트 메서드와 정적 메서드를 가질 수 있게 되었습니다. 또한 Java 9부터는 비공개 메서드와 비공개 정적 메서드도 추가되었습니다.
- 인터페이스를 구현하는 클래스는 인터페이스에서 정의한 모든 메서드를 구현해야 합니다.
- 인터페이스는 생성자를 가질 수 없습니다. 따라서 인스턴스 변수를 초기화하는 것이 불가능합니다.
- 인터페이스는 메서드의 시그니처만 제공하므로, 동작만을 정의하고 상태는 정의하지 않습니다.
- 클래스는 한 개의 클래스만 상속받을 수 있지만, 여러 개의 인터페이스를 구현할 수 있습니다.
추상 클래스와 인터페이스는 상속 받아서 구현해야 한다는 점은 같지만
추상 클래스와 인터페이스가 지니는 각각의 특징이 달라서 그에 따른 차이가 있다.
내가 위 특징을 정리해보면
추상클래스는 필드(변수)를 가질 수 있고 추상 메서드와 일반 메서드 둘 다 가질 수 있다고 할 수 있고,
인터페이스는 필드는 없다. 그리고 자바 버전 별로 다르긴 하지만 자바7까지는 추상메서드만 있다.
어떤 클래스가 있다고 하면 추상 클래스를 상속한다고 하면 하나(단일 상속)만 가능하지만
인터페이스를 상속(구현)하는 경우는 동시에 상속하는 갯수에 딱히 제한이 없다.
추상 클래스와 인터페이스는 사용하는 방식과 목적에 따라 선택하여 사용해야 합니다. 일반적으로 공통의 상태를 공유하거나 여러 클래스 간에 공통적인 동작을 정의할 때는 추상 클래스를, 여러 클래스가 동일한 동작을 공유하도록 강제하려면 인터페이스를 사용합니다.