기존 클래스에 메서드를 확장하기
기존 클래스에 메서드를 더 넣거나 있는 메서드의 행동을 변경하고 싶을 때가 분명 있다. 이러한 요구에 대응하는 프로그래밍 언어의 방법은 여러 가지가 있다.
Ruby나 JavaScript 같은 언어는 클래스를 변경 가능(mutable)하게 했다. 그래서 런타임에 메서드를 추가하거나 있는 메서드의 행동을 바꿀 수 있다. Ruby 같은 경우 이런 성질을 열린 클래스(open class)라고 하여 문화적으로 적극적으로 사용하길 장려한다.
Python 같은 언어는 클래스를 변경 가능하게 했으나 부작용이 있으므로 정말 필요한 예외적인 경우가 아니면 나쁜 것으로 간주한다. 즉, 언어적으로는 Ruby나 JavaScript와 비슷한 디자인이나 문화적으로는 오히려 터부시한다.
Java 같은 언어는 클래스는 컴파일 시점 이후에는 변경 불가능(immutable)하게 했다. 그래서 있는 클래스에 메서드를 추가하는 대신 데코레이터 패턴(decorator pattern)을 쓰거나 컴퍼지션(composition)을 극대화하는 설계가 좋은 것이라고 믿는 문화가 되었다. 어쨌든 기존 클래스에 메서드 확장하는 것은 언어적으로 불가능하며, 문화적으로도 그것이 대체로 좋지 않은 결과를 가져오기 때문에 Java에서 그게 안되는 것이 좋은 결정이었다고 생각한다.
C#은 확장 메서드(extension method) 기능을 제공한다. 클래스는 Java처럼 여전히 변경 불가능하지만 특정 영역 내에서만 메서드가 확장된 것처럼 투영해주는 기능이다.
여기에는 하나로 보이지만 사실은 두 가지 성질이 섞여있다는 것을 보여준다. 기존 클래스에 메서드를 확장하는 문제는 다음과 같은 두 가지 성질과 맞닿아 있다:
클래스를 확장하여 메서드를 추가하거나 기존 메서드의 행동을 원하는 형태로 변경하는 것은 좋은 것이다. 적은 변경으로 원하는 목표에 도달하게 해준다.
하지만 그러한 확장이 원하지 않는 범위에서도 적용되어 예기치 못한 부수 효과를 내는 것은 안 좋은 것이다.
Ruby나 JavaScript는 전자의 장점을 취하기 위해 후자의 단점을 감수하는 것이다. Python은 전자의 장점을 취하고 싶었으나 후자의 단점이 걸려서 문화적으로 쓰지 않는 방향을 제시했다. Java는 후자의 단점을 막기 위해 전자의 장점을 포기한 것이다. C#은 전자의 장점을 취하면서 후자의 단점을 제거한 것이다.
그러므로 예로 든 언어들 중에서는 C#의 방법이 정답에 제일 가깝다.