모든 메소드를 가상으로 표시해야합니까?
Java에서는 메소드를 최종으로 표시 하여 재정의가 불가능 하도록 할 수 있습니다.
C #에서는 메서드를 가상으로 표시 하여 재정의 할 수 있도록해야 합니다 .
C #에서 모든 메서드를 가상으로 표시해야 함을 의미합니까 (오버라이드하지 않으려는 몇 가지 메서드를 제외하고) 클래스를 상속 할 수있는 방법을 모를 가능성이 높기 때문입니까?
C #에서는 메서드를 가상으로 표시하여 재정의 할 수 있도록해야합니다. C #에서 모든 메서드를 가상으로 표시해야 함을 의미합니까 (오버라이드하지 않으려는 몇 가지 메서드를 제외하고) 클래스를 상속 할 수있는 방법을 알지 못할 가능성이 높기 때문입니까?
아니오. 언어 디자이너가 가상이 기본값이어야한다고 생각했다면 이것이 기본값 이되었을 것 입니다.
Overridablility는 기능 이며 모든 기능과 마찬가지로 비용 이 있습니다 . 재정의 할 수있는 메서드의 비용은 상당합니다. 특히 클래스에 "민감도"가있는 경우 큰 디자인, 구현 및 테스트 비용이 있습니다. 가상 방법은 테스트되지 않은 타사 코드를 시스템에 도입하는 방법이며 보안에 영향을 미칩니다.
클래스를 상속 할 방법을 모르는 경우 아직 디자인을 완료하지 않았 으므로 클래스를 게시하지 마십시오 . 확장 성 모델은 확실히 미리 알아야 할 것입니다. 설계 및 테스트 전략에 큰 영향을 미칩니다.
저는 모든 클래스가 봉인 되고 모든 메서드 는 봉인을 해제하거나 메서드를 가상으로 만들 실제 고객 중심의 이유가있을 때까지 비 가상적이지 않을 것을 옹호합니다 .
기본적으로 귀하의 질문은 "나는 내 고객이 내 클래스를 소비하려는 방식에 대해 무지합니다. 따라서 임의로 확장 가능하게 만들어야합니까?"입니다. 아니; 당신은 지식 이 있어야합니다 ! "내 고객이 내 클래스를 어떻게 사용할지 모르겠습니다. 모든 속성을 읽기-쓰기로해야합니까? 그리고 내 모든 메서드를 대리자 유형의 속성을 읽기-쓰기로 만들어야 내 사용자가 어떤 방법이든 자체 구현으로 대체 할 수 있습니까? " 아니요, 사용자에게 실제로 해당 기능이 필요하다는 증거 가 있을 때까지 이러한 작업을 수행하지 마십시오 ! 사용자가 실제로 원하고 필요로하는 기능을 설계, 테스트 및 구현하는 데 귀중한 시간을 할애하고 지식의 위치에서 수행하십시오.
제 생각에는 현재 받아 들여지는 대답 은 불필요하게 독단적입니다.
사실은 메서드를로 표시하지 않으면 virtual
다른 사람이 해당 동작을 재정의 sealed
할 수 없으며 다른 사람이 클래스에서 상속 할 수없는 것으로 클래스를 표시 할 때 입니다. 이것은 상당한 고통을 유발할 수 있습니다. 내 사용 사례를 예상하지 않았기 때문에 클래스를 표시 sealed
하거나 메소드 virtual
를 표시하지 않기 위해 API를 몇 번이나 저주했는지 모르겠습니다 .
이론적으로는 재정의 및 상속되는 메서드와 상속 클래스 만 허용하는 올바른 접근 방식 일 수 있지만 실제로는 가능한 모든 시나리오를 예측하는 것이 불가능하며 실제로 그렇게 폐쇄 할 좋은 이유가 없습니다.
- 타당한 이유가 없다면 클래스를
sealed
. - 라이브러리가 다른 사용자가 사용하도록 의도 된 경우 적어도 동작 을 포함하는 클래스의 주요 메서드 를
virtual
.
호출하는 한 가지 방법은 메서드 또는 속성의 이름을 보는 것입니다. List 의 GetLength () 메서드는 이름이 의미하는 바를 정확히 수행하며 많은 해석을 허용하지 않습니다 . 구현을 변경하는 것은 투명하지 않으므로 virtual
불필요한 것으로 표시 할 수 있습니다 . Add
메서드를 가상으로 표시하는 것은 누군가 Add 메서드 등을 통해 일부 개체 만 허용하는 특수 목록을 만들 수 있기 때문에 훨씬 더 유용합니다. 또 다른 예는 사용자 지정 컨트롤입니다. virtual
다른 사람들이 대부분의 동작을 사용하고 모양 만 변경할 수 있도록 기본 그리기 방법을 만들고 싶겠지 만 X 및 Y 속성을 재정의하지 않을 것입니다.
결국 당신은 종종 그 결정을 즉시 내릴 필요가 없습니다. 어쨌든 코드를 쉽게 변경할 수있는 내부 프로젝트에서는 이러한 사항에 대해 걱정하지 않습니다. 메서드를 재정의해야하는 경우이 경우 항상 가상으로 만들 수 있습니다. 반대로 프로젝트가 다른 사용자가 사용하고 업데이트 속도가 느린 API 또는 라이브러리 인 경우 어떤 클래스와 메서드가 유용 할 수 있는지 생각하는 것이 확실히 도움이됩니다. 이 경우에는 엄밀히 닫는 것보다 열려있는 것이 낫다고 생각합니다.
아니! 클래스가 상속 되는 방법 을 모르기 때문에 메서드를 재정의하려는 경우 에만 메서드를 표시 해야 합니다 .virtual
아니요. 파생 클래스에서 지정할 메서드 만 가상이어야합니다.
가상은 최종과 관련이 없습니다.
C #에서 가상 메서드 재정의를 방지하려면 sealed
public class MyClass
{
public sealed override void MyFinalMethod() {...}
}
우리는 두 진영에 대한 이유를 다시 생각해 낼 수 있지만 그것은 완전히 쓸모가 없습니다.
Java에는 의도하지 않은 수백만 개의 최종 공개 방법이 있지만 공포 이야기는 거의 듣지 않습니다.
C #에는 수백만 개의 봉인 된 공개 메서드가 있으며 우리는 공포 이야기를 거의 듣지 않습니다.
따라서 그것은 큰 문제가 아닙니다. 공용 메서드를 재정의 할 필요가 거의 없으므로 어느 쪽이든 문제가됩니다.
이것은 지역 변수가 기본적으로 최종적이어야하는지 여부라는 또 다른 인수를 상기시킵니다. 꽤 좋은 생각이지만 그것이 얼마나 가치가 있는지 과장 할 수는 없습니다. 최종적 일 수 있지만 최종적이지는 않은 수십억 개의 지역 변수가 있지만 실제 문제인 것으로 나타났습니다.
메서드를 가상으로 만들면 일반적으로 호출해야하는 코드의 속도가 느려집니다. 이러한 속도 저하는 중요하지 않지만 경우에 따라 상당히 클 수 있습니다 (가상이 아닌 메서드 호출이 인라인 될 수 있으므로 최적화 프로그램이 불필요한 작업을 제거 할 수 있기 때문입니다). 가상 호출이 실행 속도에 영향을 미칠 수있는 정도를 항상 예측할 수있는 것은 아니며, 식별 할 수있는 이점이있는 경우를 제외하고는 일반적으로 코드를 느리게 만드는 작업을 무효화해야합니다.
메서드를 비가 상으로 만드는 성능상의 이점은 대부분의 경우 메서드가 기본적으로 비가 상이라는 것을 정당화하기에 충분할 것입니다. 그러나 클래스가 상속되도록 디자인 된 경우 대부분의 메서드는 가상이고 봉인되지 않아야합니다. 비가 상 또는 봉인 된 메서드의 기본 용도는 다른 (보호 될 수있는) 가상 메서드의 래퍼로 사용되어야합니다 (기본 동작을 변경하려는 코드는 래퍼가 아닌 적절한 가상 메서드를 재정의해야합니다).
클래스를 표시 sealed
하거나 어셈블리 내의 다른 클래스에 대한 상속을 제한하는 데 성능과 관련이없는 이유가 자주 있습니다 . 무엇보다도 클래스가 외부에서 상속 가능한 경우 protected
범위가있는 모든 멤버가 공용 API에 효과적으로 추가되고 기본 클래스 의 동작이 변경되면 해당 동작 에 의존하는 파생 클래스 가 손상 될 수 있습니다. 반면에 클래스가 상속 가능한 경우 메서드를 만드는 virtual
것이 실제로 노출을 증가 시키지는 않습니다. 어떤 것이 든 파생 클래스와 더 이상 관련이없는 기본 클래스 구현의 측면을 완전히 "매립"할 수 있도록함으로써 기본 클래스 내부에 대한 파생 클래스의 의존도를 줄일 수 있습니다.List<T>
가상이었고, 그것들을 모두 덮어 쓰는 파생 클래스는 배열의 배열을 사용하여 사물을 보관할 수 있으며 (대형 객체 힙 문제 방지), 사용 된 개인 배열을 배열 List<T>
의 배열과 일치 하도록 유지하려고 할 필요가 없습니다. 배열.
아니요, 모든 메소드를 가상으로 표시해서는 안됩니다. 클래스가 상속 될 수있는 방법을 고려해야합니다. 클래스가 상속되지 않아야하는 경우 봉인 된 것으로 표시하고 멤버가 가상이 아니어야합니다. 클래스가 상속 될 가능성이있는 경우 실제로 동작을 재정의하는 기능을 최대화해야합니다. 따라서 그럴 이유가없는 한 이러한 클래스의 모든 곳에서 가상을 관대하게 사용하십시오.
참고 URL : https://stackoverflow.com/questions/14451325/should-i-mark-all-methods-virtual
'developer tip' 카테고리의 다른 글
텍스트 영역 HTML 태그의 한 줄씩 읽는 방법 (0) | 2020.10.28 |
---|---|
파이썬 주석에서 긴 URL의 형식을 지정하고 여전히 PEP8을 준수해야합니다. (0) | 2020.10.28 |
RVM 사용자에게 sudo 액세스 권한을주지 않고 RVM 시스템 요구 사항을 설치하는 방법 (0) | 2020.10.28 |
WPF로 로그 뷰어 구현 (0) | 2020.10.28 |
Rails / RSpec에서 예외 발생을 테스트하는 방법은 무엇입니까? (0) | 2020.10.28 |