phpclass/객체모델2005. 10. 11. 12:27
작성: 2008.09.05
final 키워드
final 키워드는 해당 메소드와 클래스를 변경할 수 없게 보호해 주는 역할을 합니다. final로 정의된 메소드는 재정의(overriding;오버라이딩)할 수 없으며, final로 정의된 클래스는 상속이 불가능하여 자식 클래스를 만들 수 없습니다. 이와 같이 final 키워드를 이용하면 메소드를 재정의하거나 클래스를 상속할 수 없기 때문에 메소드 또는 클래스의 내용을 적절히 보호할 수 있습니다.
클래스 내의 일부 메소드만 그 내용을 숨기려면 해당 메소드명 앞에 final 키워드를 붙이면 되고, 클래스 전체 내용을 숨기려면 클래스명 앞에 final 키워드를 붙이면 됩니다. 클래스에 final 키워드를 붙이면 해당 클래스 내의 각각의 메소드에는 final 키워드를 붙일 필요가 없이 모두 생략할 수 있습니다.
[메소드에 final 키워드 사용] 자식 클래스에서 재정의(overriding;오버라이딩)를 할 수 없음
[클래스에 final 키워드 사용] 상속이 불가능하여 자식 클래스를 만들 수 없음
자바의 경우에는 멤버 변수(필드)에도 final을 붙일 수 있는데 이는 PHP에서 멤버상수를 만들기 위하여 const를 붙이는 것과 같은 역할을 합니다.
C++의 경우에는 final 키워드의 필요성이 그리 크지 않다고 생각하여 final 키워드를 언어차원에서 지원하지 않는다고 합니다. 각 언어에 적용되는 키워드를 비교하면 아래와 같습니다.
< 각 언어별 적용 키워드 >
적용대상 C++ Java PHP
멤버변수 const final const
메소드 - final final
클래스 - final final
Final 메소드
Final 메소드는 클래스를 상속할 때 재정의(overriding;오버라이딩)할 수 없도록 구현된 메소드입니다.
[code php;gutter:true] <?php class BaseClass { final public function test() { echo "BaseClass::test() called\n"; } } class ChildClass extends BaseClass { public function test() { echo "ChildClass::test() clased\n"; } } // Fatal error: Cannot override final method BaseClass::test() ?> [/code]
< 재정의할 수 없는 Final 메소드 >
부모 클래스에서 정의된 Final 메소드는 그 구현이 변경되지 않도록 보호하기 위한 것이므로 만약 위의 예의 9행과 같이 Final 메소드를 재정의(overriding;오버라이딩)하려고 시도하게 되면 14행과 같은 에러가 발생합니다.
[code php;gutter:false] <?php class BaseClass { public function test() { echo "BaseClass::test() called\n"; } } class ChildClass extends BaseClass { final public function test() { echo "ChildClass::test() called\n"; } } // Call the override function in child class ChildClass::test(); ?> [/code]
< 자식클래스에서 정의한 Final 메소드 >
final & private
final과 private는 서로 다른 역할을 수행하는 modifier이지만 Java Language Specification-Second Edition(http://java.sun.com/docs/books/jls/second_edition/html /jTOC.doc.html)의 8.4.3.3 내용을 살펴보면 알 수 있듯이 자식 클래스에서 상속받을 수 없다는 면에서는 비슷합니다.
8.4.3.3 final Methods

A method can be declared final to prevent subclasses from overriding or hiding it. It is a compile-time error to attempt to override or hide a final method.

A private method and all methods declared in a final class (§8.1.1.2) are implicitly final, because it is impossible to override them. It is permitted but not required for the declarations of such methods to redundantly include the final keyword.

It is a compile-time error for a final method to be declared abstract.
< final & private modifier >
그러나 상속할 수 없다는 면에서는 비슷하지만 동일하지는 않습니다. final 메소드를 자식 클래스에서 재정의하면 위에서 살펴보았듯이 재정의할 수 없다는 Fatal 에러를 발생시키지만 private 메소드의 경우는 아무런 에러도 발생시키지 않습니다. 잘 동작합니다. 그렇다고 private 메소드가 자식 클래스에서 상속받아 재정의 된 것은 아닙니다. private 메소드는 상속되지 않습니다. 상속되지 않는다는 것과 상속할 수 없다는 것은 전혀 다른 의미입니다.
6.6.8 Example: private Fields, Methods, and Constructors

A private class member or constructor is accessible only within the class body in which the member is declared and is not inherited by subclasses.
< private modifier >
자식 클래스에서 부모 클래스의 private로 정의된 메소드와 동일한 이름의 메소드를 정의하더라도 이 메소드는 부모 클래스의 private 메소드와는 전혀 상관없는 새로운 메소드입니다. 왜냐하면 부모 클래스의 private 메소드는 자식 클래스로 상속되지 않기 때문에 자식 클래스에서 볼 때는 부모 클래스의 private 메소드는 없는 것과 같습니다.
[code php;gutter:true] <?php class BaseClass { private function test() { echo "BaseClass::test() called\n"; } } class ChildClass extends BaseClass { public function test() { echo "ChildClass::test() called\n"; } } // Output ChildClass::test() called ChildClass::test(); ?> [/code]
9행에서 부모 클래스에서 private로 정의된 메소드와 같은 이름의 메소드를 정의하였지만 전혀 에러가 발생하지 않았으며 15행에서 보듯이 자식 클래스에서 새롭게 정의된 메소드를 잘 실행하고 있습니다.
Final 클래스
Final 클래스는 더 이상 상속할 수 없는, 즉 자식 클래스를 만들 수 없는 클래스입니다. Final 클래스의 모든 메소드는 저절로 final 메소드가 됩니다.
[code php;gutter:true] <?php final class BaseClass { public function test() { echo "BaseClass::test() called\n"; } // Here it doesn't matter if you specify the function as final or not final public function moreTesting() { echo "BaseClass::moreTesting() called\n"; } } class ChildClass extends BaseClass { } // Fatal error: Class ChildClass may not inherit from final class (BaseClass) ?> [/code]
< Final 클래스의 예(출처: php.net) >
13행과 같이 Final 클래스를 상속하려고 시도하면 14행과 같은 에러가 발생합니다.
Final 필드
자바에만 있는 개념으로 필드는 클래스 내부에 존재하는 변수를 의미합니다. Final 필드인 경우에는 필드 내용을 변경할 수 없습니다. 이와같이 자바에서는 final 키워드를 사용하여 상수를 만들 수 있습니다.
[code java;gutter:false] final float pi = 3.141592; final boolean status = true; final int tall = 176; final int[] numbers = {1, 2, 3, 4, 5}; [/code]
< 자바에서의 Final 필드 >
이러한 자바의 Final 필드는 PHP에서 상수와 같은 개념이지요.
[code php;gutter:true] <?php class MyClass { const pi = 3.141592; const status = true; const tall = 176; // Fatal error: Arrays are not allowed in class constants const numbers = array(1, 2, 3, 4, 5); } echo MyClass::pi . "\n"; echo MyClass::status . "\n"; echo MyClass::tall . "\n"; echo MyClass::numbers . "\n"; ?> [/code]
< PHP에서의 상수 정의와 사용법 >
자바와는 달리 PHP에서는 7행, 13행에서와 같이 배열 상수를 정의하여 사용할 수 없으므로 에러가 발생합니다. 참고로 자바에서의 배열 상수는 다른 형식의 상수와 좀 다른 의미를 가지고 있습니다. 배열명(변수형식, 차원, 배열크기 ...) 자체가 상수라는 의미이며 각 배열 항목의 값은 언제든지 변경할 수 있습니다.

Posted by 방글24