Dart 공식 문서에도 명시되어있지만 부모 클래스의 필드를 오버라이딩 하는것은 좋지 않습니다. 사실 필드를 오버라이딩해서 써야하는 경우는 많이 없을 것 같긴 한데, 이번에 코드를 보다가 필드를 오버라이딩 한 경우 린트가 발생하는 것을 보고 간단히 알아보는 시간을 가졌습니다.
먼저, 아래 클래스를 오버라이딩 할 경우 다음처럼 린트가 발생합니다.
abstract class Recipt {
String? name;
String? price;
void printReceipt();
}
결론부터 말하자면 메모리 관리 측면에서 필드를 오버라이딩 하는것은 좋지 않습니다.
일반적인 필드, 즉 인스턴스 변수는 클래스의 인스턴스가 생성될 때마다 같이 메모리에 할당됩니다. 따라서 위 코드처럼 부모 클래스의 필드를 오버라이딩하여 값을 할당할 경우, 부모 클래스의 필드에 대한 메모리도 할당되어 더 많은 메모리를 사용하게 됩니다.
상식일수도 있지만 저는 여기서 다음의 궁금증이 생겼습니다.
인스턴스 함수와 인스턴스 변수는 메모리에 할당되는 방식이 다릅니다. 앞서 언급했듯 클래스의 필드는 인스턴스가 생성될 때마다 추가로 메모리에 할당됩니다. 즉 인스턴스가 생성될 때마다 변수를 위한 공간이 메모리에 하나씩 더 생성됩니다.
하지만 함수의 경우 인스턴스가 생성될 때마다 생성되지 않습니다. 프로그램이 실행되어 클래스가 최초로 메모리에 할당될 때 일반 함수, 오버라이딩된 함수, static 함수 모두 바이트코드로 변역되어 메모리에 저장되고, 각 인스턴스들은 필요 시 메모리에 저장된 함수의 위치, 즉 주소값을 이용해 미리 저장된 함수를 호출합니다. 함수는 변하지 않는 코드블록이며 인스턴스 생성 시마다 코드블록이 중복으로 메모리에 저장되는 것은 비효율적이기 때문입니다.
Dart에서는 부모 클래스의 필드를 오버라이딩해서 사용하는 것이 권장되지 않습니다. 만약 꼭 해야한다면, 아래 코드처럼 부모 필드의 getter와 setter를 오버라이딩해서 사용합시다.
Dart - overridden fields
overridden_fields documentation is vague #2428
[Java] 메모리 구조