UFO ET IT

기본적으로 봉인 클래스를 권장해야합니까?

ufoet 2020. 11. 21. 08:37
반응형

기본적으로 봉인 클래스를 권장해야합니까?


큰 프로젝트에서 나는 다른 프로그래머가 자신의 클래스를 하위 클래스로 분류하는 방법을 고려하지 않은 경우 항상 클래스를 봉인하도록 권장하는 것을 고려하고 있습니다. 경험이 적은 프로그래머는 종종 이것을 고려하지 않습니다.

Java 및 C #에서 클래스가 봉인되지 않은 / 최종이 아닌 pr 기본값이라는 것이 이상합니다. 클래스를 봉인하면 코드의 가독성이 크게 향상된다고 생각합니다.

이것은 우리가 서브 클래 싱해야하는 드문 경우가 발생하는 경우 항상 변경할 수있는 내부 코드입니다.

당신의 경험은 무엇입니까? 나는이 생각에 대해 꽤 많은 저항을 받는다. 게으른 사람들은 "봉인"이라고 입력하는 것을 귀찮게 할 수 없습니까?


좋아요, 다른 많은 사람들이 무게를 쪘기 때문에 ...

예, 클래스가 기본적으로 봉인되도록 권장하는 것이 전적으로 합리적이라고 생각합니다.

이것은 그의 뛰어난 저서 Effective Java, 2nd edition 에서 Josh Bloch의 권장 사항과 함께 진행됩니다 .

상속을 위해 설계하거나 금지하십시오.

상속을위한 디자인은 어렵고 , 특히 가상 메서드 중 하나가 다른 메서드를 호출하는 경우 구현의 유연성이 떨어질 수 있습니다 . 과부하 일 수도 있고 아닐 수도 있습니다. 메서드가 다른 메서드를 호출한다는 사실은 문서화되어 있어야합니다. 그렇지 않으면 두 메서드 중 하나를 안전하게 재정의 할 수 없습니다. 언제 호출 될지 또는 스택 오버플로 위험없이 다른 메서드를 호출 할 수 있는지 여부를 알 수 없습니다.

이제 이후 버전에서 어떤 메서드 호출을 변경하려는 경우 변경할 수 없습니다. 잠재적으로 하위 클래스를 중단 할 수 있습니다. 따라서 "유연성"이라는 이름으로 실제로 구현의 유연성을 떨어 뜨리고 구현 세부 사항을 더 자세히 문서화해야했습니다. 그것은 나에게 좋은 생각처럼 들리지 않습니다.

다음은 불변성입니다. 저는 불변 유형을 좋아합니다. 변경 가능한 유형보다 추론하기가 더 쉽습니다. 그것은 하나의 이유입니다 Joda 시간 API를 사용하는 것보다 좋네요 DateCalendar자바있다. 그러나 봉인되지 않은 클래스는 불변 이라고 결코 수 없습니다. 유형의 매개 변수를 수락하면 Foo선언 된 속성에 의존 할 수 있습니다 .Foo시간이 지남에 따라 변경되지는 않지만 수정되지 않는 객체 자체에 의존 할 수는 없습니다. 하위 클래스에 변경 가능한 속성이있을 수 있습니다. 그 속성이 일부 가상 방법의 재정의에서도 사용되는 경우 천국이 저를 도와줍니다. 불변성의 많은 이점에 작별을 고하십시오. (역설적으로, Joda Time은 매우 큰 상속 계층을 가지고 있습니다. 종종 "하위 클래스는 불변해야합니다. 큰 상속 계층은 ChronologyC #으로 이식 할 때 이해하기 어렵게 만들었습니다.)

마지막으로 상속의 남용 측면이 있습니다. 개인적으로 가능한 경우 상속보다 구성을 선호합니다. 저는 인터페이스에 대한 다형성을 좋아하고 때때로 구현 상속을 사용하지만 제 경험에는 거의 적합하지 않습니다. 클래스를 봉인하면 구성이 더 적합한 위치에서 부적절하게 파생 되는 것을 방지 할 수 있습니다.

편집 : 2004 년부터 Eric Lippert의 블로그 게시물에서 많은 프레임 워크 클래스가 봉인 된 이유를 독자들에게 소개하고 싶습니다 . .NET 이 테스트 가능성을 위해 작업 할 수 있는 인터페이스를 제공했으면하는 곳이 많이 있지만 이는 약간 다른 요청입니다.


중요한 것을 다른 개발자 (향후 유지 보수 개발자 포함)와 소통하기 위해 건축 설계 결정이 내려진다는 것이 제 생각입니다.

봉인 클래스는 구현이 재정의되지 않아야 함을 전달합니다. 클래스를 가장해서는 안된다는 것을 알립니다. 봉인하는 데에는 좋은 이유가 있습니다.

모든 것을 봉인하는 비정상적인 접근 방식을 취한다면 (그리고 이것은 비정상적입니다), 디자인 결정은 이제 실제로 중요하지 않은 것을 전달합니다. 예를 들어 원래 / 저자 개발자 가 클래스를 상속 하도록 의도 한 것이 아닙니다 .

그렇다면 클래스 어떤 이유로 상속 되어서는 안된다는 것을 다른 개발자에게 어떻게 전달할 수 있습니까? 당신은 정말 할 수 없습니다. 당신은 붙어 있습니다.

또한 클래스 봉인은 가독성을 향상시키지 않습니다. 나는 단지 그것을 보지 않는다. 상속이 OOP 개발에서 문제라면 우리는 훨씬 더 큰 문제를 안고 있습니다.


나는 내가 합리적으로 경험이 많은 프로그래머라고 생각하고 싶다. 그리고 내가 아무것도 배운 것이 없다면 미래를 예측하는 데 현저히 나쁘다는 것이다.

봉인을 입력하는 것은 어렵지 않습니다. 저는 약간의 상속으로 문제를 쉽게 해결할 수 있다는 것을 발견하는 개발자 (나일 수 있습니다!)를 짜증나게하고 싶지 않습니다.

나는 또한 클래스 봉인이 어떻게 더 읽기 쉽게 만드는지 전혀 모른다. 사람들이 상속보다 구성을 선호하도록 강요하려고합니까?


클래스에서 상속하는 데 문제가 있어서는 안됩니다.

상속되지 않아야하는 정당한 이유가있을 때만 클래스를 봉인해야합니다.

게다가, 그것들을 모두 봉인하면 유지 보수성을 감소시킬뿐입니다. 누군가 당신의 클래스 중 하나에서 상속 받기를 원할 때마다, 그는 그것이 봉인 된 것을 보게 될 것입니다. 그리고 나서 그는 봉인을 제거 할 것입니다. 자신을위한 수업.

그런 다음 동일한 것의 두 가지 구현, 하나는 다른 것보다 더 나쁠 수 있으며 유지 관리 할 코드는 두 가지입니다.

봉인되지 않은 상태로 유지하는 것이 좋습니다. 개봉해도 해가 없습니다.


솔직히 저는 C #에서 기본적으로 봉인되지 않은 클래스가 나머지 기본값이 언어에서 작동하는 방식과 함께 이상하고 제자리에 있지 않다고 생각합니다.

기본적으로 클래스는 internal. 기본적으로 필드는 private입니다. 기본적으로 구성원은 private입니다.

기본적으로 액세스 가능성이 가장 낮다는 경향이있는 것 같습니다. 그것은 이유에 서 것 그 unsealed대신의 C #에서 키워드 정상적으로 종료 sealed.

개인적으로 나는 수업이 기본적으로 봉인되기를 바랍니다. 누군가가 클래스를 작성할 때 대부분의 경우, 그는 서브 클래 싱과 그에 수반되는 모든 복잡성을 염두에두고 그것을 디자인하지 않습니다. 미래의 서브 클래 싱을위한 설계는 의식적인 행동이어야하므로 명시 적으로 언급해야합니다.


© 제프리 리히터

봉인 된 클래스가 봉인되지 않은 클래스보다 나은 이유는 세 가지입니다.

  • 버전 관리 : 클래스가 원래 봉인 된 경우 호환성을 깨지 않고 향후 봉인되지 않음으로 변경 될 수 있습니다. 그러나 일단 클래스가 봉인되지 않으면 모든 파생 클래스가 중단되므로 나중에 봉인으로 변경할 수 없습니다. 또한 봉인되지 않은 클래스가 봉인되지 않은 가상 메서드를 정의하는 경우 가상 메서드 호출의 순서를 새 버전으로 유지해야합니다. 그렇지 않으면 나중에 파생 된 형식을 손상시킬 가능성이 있습니다.
  • 성능 : 이전 섹션에서 설명했듯이 가상 메서드 호출은 호출 할 메서드를 정의하는 형식을 결정하기 위해 CLR이 런타임에 개체 형식을 조회해야하기 때문에 비가 상 메서드 호출만큼 잘 수행되지 않습니다. 그러나 JIT 컴파일러가 봉인 된 형식을 사용하는 가상 메서드에 대한 호출을 확인하면 JIT 컴파일러는 메서드를 비가 상으로 호출하여보다 효율적인 코드를 생성 할 수 있습니다. 클래스가 봉인 된 경우 파생 클래스가있을 수 없음을 알고 있기 때문에이를 수행 할 수 있습니다.
  • Security: and predictability A class must protect its own state and not allow itself to ever become corrupted. When a class is unsealed, a derived class can access and manipulate the base class’s state if any data fields or methods that internally manipulate fields are accessible and not private. In addition, a virtual method can be overridden by a derived class, and the derived class can decide whether to call the base class’s implementation. By making a method, property, or event virtual, the base class is giving up some control over its behavior and its state. Unless carefully thought out, this can cause the object to behave unpredictably, and it opens up potential security holes.

I only seal classes if I am working on a reusable component that I intend to distribute, and I don't want the end user to inherit from it, or as a system architect if I know I don't want another developer on the team to inherit from it. However there is usually some reason for it.

Just because a class isn't being inherited from, I don't think it should automatically be marked sealed. Also, it annoys me to no end when I want to do something tricky in .NET, but then realize MS marks tons of their classes sealed.


This is a very opinionated question that's likely to garner some very opinionated answers ;-)

That said, in my opinion, I strongly prefer NOT making my classes sealed/final, particularly at the beginning. Doing this makes it very difficult to infer the intended extensibility points, and it's nearly impossible to get them right at the beginning. IMHO, overuse of encapsulation is worse than overuse of polymorphism.


"...consider[ing] how their classes should be sub classed..." shouldn't matter.

At least a half dozen times over the past few years I've found myself cursing some open source team or another for a sloppy mix of protected and private, making it impossible to simply extend a class without copying the source of the entire parent class. (In most cases, overriding a particular method required access to private members.)

One example was a JSTL tag that almost did what I wanted. I need to override one small thing. Nope, sorry, I had to completely copy the source of the parent.


I don't like that way to think. Java and c# are made to be OOP languages. These languages are designed in a way where a class can have a parent or a child. That's it.

Some people say that we should always start from the most restricting modifier (private, protected...) and set your member to public only when you use it externally. These people are ,to me, lazy and don't want to think about a good design at the beginning of the project.

My answer is: Design your apps in a good way now. Set your class to seal when it needs to be sealed and private when it needs to be private. Don't make them sealed by default.


The main purpose of a sealed class to take away the inheritance feature from the user so they cannot derive a class from a sealed class.Are you sure you want to do that. Or do you want to start having all classes as sealed and then when you need to make it inheritable you will change it .. Well that might be ok when every thing is in house and in one team but incase other teams in future use your dlls it will be not possible to recompile whole source code everytime a class needs to be unsealed .... I wont recommend this but thats just my opinion


Your house, your rule.

You can also have the complementary rule instead: a class that can be subclassed must be annotated; nobody should subclass a class that's not annotated so. This rule is not harder to follow than your rule.


I find that sealed / final classes are actually pretty rare, in my experience; I would certainly not recommend suggesting all classes be sealed / final by default. That specification makes a certain statement about the state of the code (i.e., that it's complete) that is not necessarily always true during development time.

I'll also add that leaving a class unsealed requires more design / test effort to make sure that the exposed behaviours are well-defined and tested; heavy unit testing is critical, IMO, to achieve a level of confidence in the behaviour of the class that appears to be desired by the proponents of "sealed". But IMO, that increased level of effort translates directly to a high level of confidence and to higher quality code.

참고URL : https://stackoverflow.com/questions/6389417/should-i-recommend-sealing-classes-by-default

반응형