Classes
have members, and it is entirely possible for the member of a class
to be another user-defined type. Thus, a Button
class might have a member of type Location
, and a
Location
class might contain members of type
Point
. Finally, Point
might
contain members of type int
.
At times, the contained class might exist only to serve the outer
class, and there might be no reason for it to be otherwise visible.
(In short, the contained class acts as a helper class.) You can
define the helper class within the definition of the outer class. The
contained, inner class is called a
nested
class, and the class that contains it
is called, simply, the
outer
class.
Nested classes have the advantage of access to all the members of the outer class. A method of a nested class can access private members of the outer class.
In addition, the nested class can be hidden from all other classes—that is, it can be private to the outer class.
Finally, a nested class that is public is accessed within the scope
of the outer class. If Outer
is the outer class,
and Nested
is the (public) inner class, you refer
to Nested
as Outer.Nested
, with
the outer class acting (more or less) as a namespace or scope.
Java programmers take note: nested classes are roughly equivalent to static inner classes; there is no C# equivalent to Java’s nonstatic inner classes.
Example 5-6 adds a nested class to
Fraction
named FractionArtist
.
The job of FractionArtist
is to render the
fraction on the console. In this example, the rendering has been
replaced with a pair of simple WriteLine( )
statements. The
Fraction
class has also been stripped down to its
essentials.
Example 5-6. Using a nested class
using System; using System.Text; public class Fraction { public Fraction(int numerator, int denominator) { this.numerator=numerator; this.denominator=denominator; } // Methods elided... public override string ToString( ) { StringBuilder s = new StringBuilder( ); s.AppendFormat("{0}/{1}", numerator, denominator); return s.ToString( ); }internal class FractionArtist
{
public void Draw(Fraction f)
{
Console.WriteLine("Drawing the numerator: {0}",
f.numerator);
Console.WriteLine("Drawing the denominator: {0}",
f.denominator);
}
}
private int numerator; private int denominator; } public class Tester { static void Main( ) { Fraction f1 = new Fraction(3,4); Console.WriteLine("f1: {0}", f1.ToString( )); Fraction.FractionArtist fa = new Fraction.FractionArtist( ); fa.Draw(f1); } }
The Fraction
class is generally unchanged with the
exception of adding the new nested
class and
eliding a number of methods that are not relevant to this issue. The
nested class is shown in bold. The FractionArtist
class provides only a single member, the Draw( )
method. What is particularly interesting is that Draw( )
has access to the private data members
f.numerator
and f.denominator
,
to which it would not have had access if it were not a nested class.
Notice in Main( )
that to declare an instance of
this nested class, you must specify the type name of the outer class:
Fraction.FractionArtist fa = new Fraction.FractionArtist( );
Even though FractionArtist
is
public
, it is scoped to within the
Fraction
class.
3.16.218.221