I am working on some legacy code and have come across something that I'm not sure of. We have a class y
that is declared inside of another class x
. Class y
is only ever used inside of class x
but my question is why wouldn't you create a separate class file and put class y
in there instead of declaring it inside of class x
? Isn't this violating OOP's or is it just a matter of style since it is only ever used inside of this class. I'm refactoring some of this code and my first reaction would be to separate class y
out into it's own file.
namespace Library { public class x { // methods, properties, local members of class x class y { // methods, properties, local members of class y } } }
A class can be declared within the scope of another class. Such a class is called a "nested class." Nested classes are considered to be within the scope of the enclosing class and are available for use within that scope.
Nested Classes in C++A nested class is a class that is declared in another class. The nested class is also a member variable of the enclosing class and has the same access rights as the other members. However, the member functions of the enclosing class have no special access to the members of a nested class.
You cannot forward declare a nested structure outside the container. You can only forward declare it within the container.
The scope of a nested class is bounded by the scope of its enclosing class. Thus in below example, class NestedClass does not exist independently of class OuterClass. A nested class has access to the members, including private members, of the class in which it is nested.
You create an inner class because it is only ever used within the scope of class x and it logically fits in the factoring/architecture of class x.
Class y might also be privy to implementation details of class x that are not meant to be known to the public.
This has permissions implications. A top-level "class y" would be "internal" - however, here "y" is private to "x". This approach is helpful for implementation details (for example cache rows etc). Likewise, y
has access to all private state of x
.
There are also implications with generics; x<T>.y
is generic "of T", inherited from the outer class. You can see this here, where Bar
has full use of T
- and note that any static fields of Bar
are scoped per-T
.
class Foo<T> { void Test(T value) { Bar bar = new Bar(); bar.Value = value; } class Bar { public T Value { get; set; } } }
Often people incorrectly think they need to define Bar
as Bar<T>
- this is now (effectively) doubly generic - i.e. Foo<TOld, T>
- where TOld
is the (now unavailable) T
from Foo<T>
. So don't do that! Or if you want it to be doubly-generic, pick different names. Fortunately, the compiler warns you about this...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With