Where and how to use nested classes? [duplicate] - c#

This question already has answers here:
Why/when should you use nested classes in .net? Or shouldn't you?
(14 answers)
Closed 10 years ago.
I am thinking that if a class will be instantiated only in another class so it is right to use it nested in that class.I think this will help us good design.When i look at my project i have almost never seen such nested structure.But if i try to nested classes so this time another questions appear in my mind.For example
I have Board class, Move classes such as ShortCastle,LongCastle,EnPassant,Promote and Pieces like Pawn,Queen,Rook,Knight etc. So it is clear Board classes will instantiate Piece classes and Piece classes will instantiate Move classes. For a good design,Promote move class should to be nested of Pawn because only pawn can promote itself.short and long Castles should to be nested of King because only king can have such type moves.
Trying to put all Piece classes into Board class is not looking good design because 8-9 class will be inside of Board class and it will really annoying one Board class file will be too large and hardly readable.I prefer keep each piece class in another file. Good that we can create partial Board class but still isn't it annoying 8-9 Partial Board class files will hold each piece class? Is it better to not make them nested ? Same about Pieces Create another partial Piece file just for another Move type class ? If nested class just take small space so it wouldn't be any problem but if it takes many methods ?

I think you are too generous with nested classes.
Have a look at this design guideline for nested types.
Do not use nested types if the following are true:
The type must be instantiated by
client code. If a type has a public
constructor, it probably should not
be nested. The rationale behind this
guideline is that if a nested type
can be instantiated, it indicates
that the type has a place in the
library on its own. You can create
it, use it, and destroy it without
using the outer type. Therefore, it
should not be nested. An inner type
should not be widely reused outside
of the outer type without a
relationship to the outer type.
References to the type are commonly
declared in client code.
The pieces may belong to a board(Piece-collection as a member?) but could coexist without of it. You might f.e. want to reuse boards without pieces(themes etc) and also reuse pieces without a board(positions etc).

Private members from parent class are accessible to Nexted Class methods.
Nexted class allows reduce complexity without broad Scope.

For a good design,Promote move class should to be nested of Pawn because only pawn can promote itself.
I don't really agree. Just because you can nest classes doesn't mean you should. Ask yourself what benefit you're getting from nesting these classes.

If you truly, truly think nested classes make sense for your design (see Tim Schmelter's admonitions) but feel the file size is too big, the use of partial classes is fine to split the nested class defintions into their own files. Or if the nested classes are small enough on their own but you have a large number of them, put all the nested classes into one partial file.
Parent.cs:
public partial class Parent
{
void SomeMethod()
{
Nested1 n1 = new Nested1();
Nested2 n2 = new Nested2();
}
}
Nested.cs:
public partial class Parent
{
private class Nested1
{
}
private class Nested2
{
}
}

Nested classes have their place but can be confusing to work with. I found a webpage that shows how to use some .Net classes to get Facebook's JSON-output of wall posts at http://www.virtualsecrets.com/graph-api-json-facebook-handler.html What is interesting here is that classes are nested inside of classes, inside of other classes - so it can be done, just a bit complex. :)

Related

Merging two class structures which each rely on complex inheritance c#

We have a massive code set, so each of the classes is of the form:
public class A :
DPM<Time, Data, TypeAKindA,
TypeAKindB, TypeAKindC,
TypeAKindC, TypeAkindD, TypeAKindE>
public class B:
DPM<Temp, Data, TypeBKindA,
TypeBKindB, TypeBKindB,
TypeBKindC, TypeBKindD, TypeBKindE>
So Time is specific struct for example which differs from Temp.
The problem, is for each of these classes I have an init, constructor, so for example in the init, I am doing this specific to the class name. I.e. A goes off and does something specific for each class.
This is a massive code-set so I cannot re-factor. I'd like to combine these, so I have one class call it C, that will basically either execute the functionality of each or somehow merge them. I cannot change class DPM, and this is a complex structure with plenty of where clauses in it.
It looks like this:
public abstract class DPM<TypeA, TypeB, TypeC, , ... > : ID
where ID is an interface.
An example of the issue is the class DPM inherited has a property called _xyz which is populated with different values in .init() depending on whether it is called from Class A or Class B. And I don't know the dependencies downstream - so where is called or used later in the code.
Any suggestions very welcome.
So you cannot refactor, but you are trying to refactor it. You will need to rename any common properties of differing types. Of course, this begs the question of whether you should do so.
I would suggest that chaining additional types onto the class definition would only make matters worse. That being the case, you could possibly refactor to common interfaces. Have you considered posting a more detailed question on StackExchange's CodeReview site?

Nested class in C#

I am trying to study about nested class in c#. After reading many documents and goggling, I still not yet clear about when to use nested classes. But as far as I understand I did a small sample program. I am pasting my code below. Is this nested class program implemented in correct logic? . What actually a nested class using for ?. and also I have a doubt arise in this program and I specified that doubt in the program. Please help me ...
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Bank bankObj = new Bank();
bankObj.CreateAccount();
bankObj.ShowMyAccountNumber();
}
}
class Bank
{
static int accountNumber; // here if I just declare this as int accountNumber without static it showing an error in the CreatePersonalAccount(int accNo) method's first line ie accountNumber = accNo; as "Cannot access a non-static member of outer type." What actually this error mean ?
public class BankAccountSection
{
public bool CreatePersonalAccount(int accNo)
{
accountNumber = accNo;
return true;
}
}
public void CreateAccount()
{
bool result = new BankAccountSection().CreatePersonalAccount(10001);
}
public void ShowMyAccountNumber()
{
MessageBox.Show(accountNumber.ToString());
}
}
Nested classes are usually used for small utility classes that have no use outside the enclosing (outer) class. For that reason, nested classes are usually private. (There's even an FxCop rule for that.)
Your code
In your case, the nested class BankAccountSection is not really useful, since it has no state by itself. CreatePersonalAccount might as well just be a method of the outer class.
Regarding static int accountNumber;: This will make accountNumber a shared field across all Bank objects, which defeats the whole purpose. Don't do that. If you really need to set a field of the Bank object inside the inner class, you need to pass a reference of the Bank object to the inner class. (This is different to Java, where such a reference is available automatically under some circumstances.) In your particular case, just get rid of the inner class.
Examples for legitimate use cases
You have a large algorithm inside a method. You realize that extracting this algorithm into its own class using many small methods and instance variables would increase readability. Since the algorithm is very specific and probably not useful for other classes, you put the algorithm into an inner class. Thus, you avoid cluttering your outer class with instance variables only used by that algorithm.
You create a List data structure, which is internally implemented as a linked list. Since you don't expose the list nodes to the outside world, you make the nodes an inner class.
Related:
Why/when should you use nested classes in .net? Or shouldn't you?
You seem to think that nested classes in C# behave how they do in Java. That in other words, unless a nested class is declared as static, that it will share the instance of the enclosing class. In C# this is not the case. There is no such thing as that sort of thing in C# -- all nested classes are implicitly static.
This is why you cannot access accountNumber from the nested class unless that field is declared static. (Since the nested class has no access to any particular instance) The idomatic solution to this problem in C# is to pass the instance of the enclosing class into the nested class (presumably by passing this via a constructor argument when instantiating it).
First, that's not a nested class, they are just two classes in one file.
Now, even if it were a nested class, this would probably be an example of when NOT to use nested classes. You should definitely separate your logic from your GUI logic.
I'm don't really think you should be using nested classes anyway, they are in my opinion hard to mantain, but I might be wrong. If I really needed to use nested classes I'd probably do so only when the child class is tightly related.
The error is because you can not access a member of a non static class without its object.
if you do so then it must be declared static.

What are reasons why one would want to use nested classes? [duplicate]

This question already has answers here:
Why/when should you use nested classes in .net? Or shouldn't you?
(14 answers)
Closed 10 years ago.
In this stackoverflow answer a commenter mentioned that "private nested classes" can be quite useful so I was reading about them in articles such as this one which tend to explain how nested classes function technically, but not why you would use them.
I suppose I would use private nested classes for little helper classes that belong to a larger class, but often I will need a helper class from another class and so I would just have to take the extra effort to (1) make the nested class non-nested or (2) make it public and then access it with the outer-class prefix on it, which both seems to be extra work without any added-value for having the nested class in the first place. Hence in general I really don't see a use case for nested classes, other than perhaps to keep classes a bit more organized into groups, but I that also goes against the one-class-per-file clarity that I have come to enjoy.
In what ways do you use nested classes to make your code more manageable, readable, efficient?
You've answered your own question. Use nested classes when you need a helper class that is meaningless outside the class; particularly when the nested class can make use of private implementation details of the outer class.
Your argument that nested classes are useless is also an argument that private methods are useless: a private method might be useful outside of the class, and therefore you'd have to make it internal. An internal method might be useful outside of the assembly, and therefore you'd make it public. Therefore all methods should be public. If you think that's a bad argument, then what is different about you making the same argument for classes instead of methods?
I make nested classes all the time because I am frequently in the position of needed to encapsulate functionality in a helper that makes no sense outside of the class, and can use private implementation details of the outer class. For example, I write compilers. I recently wrote a class SemanticAnalyzer that does semantic analysis of parse trees. One of its nested classes is LocalScopeBuilder. Under what circumstances would I need to build a local scope when I am not analyzing the semantics of a parse tree? Never. That class is entirely an implementation detail of the semantic analyzer. I plan to add more nested classes with names like NullableArithmeticAnalyzer and OverloadResolutionAnalyzer that are also not useful outside of the class, but I want to encapsulate rules of the language in those specific classes.
People also use nested classes to build things like iterators, or comparators - things that make no sense outside of the class and are exposed via a well-known interface.
A pattern I use quite frequently is to have private nested classes that extend their outer class:
abstract public class BankAccount
{
private BankAccount() { }
// Now no one else can extend BankAccount because a derived class
// must be able to call a constructor, but all the constructors are
// private!
private sealed class ChequingAccount : BankAccount { ... }
public static BankAccount MakeChequingAccount() { return new ChequingAccount(); }
private sealed class SavingsAccount : BankAccount { ... }
and so on. Nested classes work very well with the factory pattern. Here BankAccount is a factory for various types of bank account, all of which can use the private implementation details of BankAccount. But no third party can make their own type EvilBankAccount that extends BankAccount.
Returning an interface to the caller whose implementation you want to hide.
public class Outer
{
private class Inner : IEnumerable<Foo>
{
/* Presumably this class contains some functionality which Outer needs
* to access, but which shouldn't be visible to callers
*/
}
public IEnumerable<Foo> GetFoos()
{
return new Inner();
}
}
Private helper classes is a good example.
For instance, state objects for background threads. There is no compelling reason to expose those types. Defining them as private nested types seems a quite clean way to handle the case.
I use them when two bound values (like in a hash table) are not enough internally, but are enough externally. Then i create a nested class with the properties i need to store, and expose only a few of them through methods.
I think this makes sense, because if no one else is going to use it, why create an external class for it? It just doesn't make sense to.
As for one class per file, you can create partial classes with the partial keyword, which is what I usually do.
One compelling example I've run into recently is the Node class of many data structures. A Quadtree, for example, needs to know how it stores the data in its nodes, but no other part of your code should care.
I've found a few cases where they've been quite handy:
Management of complex private state, such as an InterpolationTriangle used by an Interpolator class. The user of the Interpolator doesn't need to know that it's implemented using Delauney triangulation and certainly doesn't need to know about the triangles, so the data structure is a private nested class.
As others have mentioned, you can expose data used by the class with an interface without revealing the full implementation of a class. Nested classes can also access private state of the outer class, which allows you to write tightly coupled code without exposing that tight coupling publicly (or even internally to the rest of the assembly).
I've run into a few cases where a framework expects a class to derive from some base class (such as DependencyObject in WPF), but you want your class to inherit from a different base. It's possible to inter-operate with the framework by using a private nested class that descends from the framework base class. Because the nested class can access private state (you just pass it the parent's 'this' when you create it), you can basically use this to implement a poor man's multiple inheritance via composition.
I think others have covered the use cases for public and private nested classes well.
One point I haven't seen made was an answer your concern about one-class-per-file. You can solve this by making the outer class partial, and move the inner class definition to a separate file.
OuterClass.cs:
namespace MyNameSpace
{
public partial class OuterClass
{
// main class members here
// can use inner class
}
}
OuterClass.Inner.cs:
namespace MyNameSpace
{
public partial class OuterClass
{
private class Inner
{
// inner class members here
}
}
}
You could even make use of Visual Studio's item nesting to make OuterClass.Inner.cs a 'child' of OuterClass.cs, to avoid cluttering your solution explorer.
One very common pattern where this technique is used is in scenarios where a class returns an interface or base class type from one of its properties or methods, but the concrete type is a private nested class. Consider the following example.
public class MyCollection : IEnumerable
{
public IEnumerator GetEnumerator()
{
return new MyEnumerator();
}
private class MyEnumerator
{
}
}
I usually do it when I need a combination of SRP (Single Responsibility Principal) in certain situations.
"Well, if SRP is your goal, why not split them into different classes?" You will do this 80% of the time, but what about situations where the classes you create are useless to the outside world? You don't want classes that only you will use to clutter your assembly's API.
"Well, isn't that what internal is for?" Sure. For about 80% of these cases. But what about internal classes who must access or modify the state of public classes? For example, that class which was broken up into one or more internal classes to satisfy your SRP streak? You would have to mark all the methods and properties for use by these internal classes as internal as well.
"What's wrong with that?" Nothing. For about 80% of these cases. Of course, now you're cluttering the internal interface of your classes with methods/properties that are only of use to those classes which you created earlier. And now you have to worry about other people on your team writing internal code won't mess up your state by using those methods in ways that you hadn't expected.
Internal classes get to modify the state of any instance of the type in which they are defined. So, without adding members to the definition of your type, your internal classes can work on them as needed. Which, in about 14 cases in 100, will be your best bet to keep your types clean, your code reliable/maintainable, and your responsibilities singular.
They are really nice for, as an example, an implementation of the singleton pattern.
I have a couple of places where I am using them to "add" value, as well. I have a multi-select combobox where my internal class stores the state of the checkbox and the data item as well. no need for the world to know about/use this internal class.
Private anonymous nested classes are essential for event handlers in the GUI.
If some class is not part of the API another class exports, it must be made private. Otherwise you are exposing more than you intend. The "million dollar bug" was an example of this. Most programmers are too slack about this.
Peter
The question is tagged C# so I'm not sure this is of interest, but in COM you can use inner classes to implement interfaces when a class C++ implements multiple COM interfaces... essentially you use it for composition rather than multiple-inheritance.
Additionally in MFC and perhaps other technologies you might need your control/dialog to have a drop-target class, which makes little sense other than as a nested class.
If it is necessary for an object to return some abstract information about its state, a private nested class may be suitable. For example, if an Fnord supports "save context" and "restore context" methods, it may be useful to have the "save context" function return an object of type Fnord.SavedContext. Type access rules aren't always the most helpful; for example, it seems difficult to allow Fnord to access properties and methods of a Fnord.SavedContext without making such properties and methods visible to outsiders. On the other hand, one could have Fnord.CreateSaveContext simply create a New Fnord.SaveContext with the Fnord as a parameter (since Fnord.SaveContext can access the internals of Fnord), and Fnord.LoadContextFrom() can call Fnord.SaveContext.RestoreContextTo().

Why do we need to have Object class as baseclass for all the classes?

Either in C# or Java or in any other language which follows oops concepts generally has 'Object' as super class for it by default. Why do we need to have Object as base class for all the classes we create?
When multiple inheritance is not possible in a language such as C# or Java how can we derive our class from another class when it is already derived from Object class. This question may look like silly but wanted to know some experts opinions on it.
Having a single-rooted type hierarchy can be handy in various ways. In particular, before generics came along, it was the only way that something like ArrayList would work. With generics, there's significantly less advantage to it - although it could still be useful in some situations, I suspect. EDIT: As an example, LINQ to XML's construction model is very "loose" in terms of being specified via object... but it works really well.
As for deriving from different classes - you derive directly from one class, but that will in turn derive indirectly from another one, and so on up to Object.
Note that the things which "all objects have in common" such as hash code, equality and monitors count as another design decision which I would question the wisdom of. Without a single rooted hierarchy these design decisions possibly wouldn't have been made the same way ;)
The fact that every class inherits object ensured by the compiler.
Meaning that is you write:
class A {}
It will compile like:
class A : Object{}
But if you state:
class B : A {}
Object will be in the hierarchy of B but not directly - so there is still no multiple inheritance.
In short
1) The Object class defines the basic state and behavior that all objects must have, such as the ability to compare oneself to another object, to convert to a string, to wait on a condition variable, to notify other objects that a condition variable has changed, and to return the object's class.
2) You can have B extend C, and A extend B. A is the child class of B, and B is the child class of C. Naturally, A is also a child class of C.
Well, the multiple inheritance of Object does not apply - you can think of it as:
"If a type doesn't have a base type, then implicitly inject Object".
Thus, applying the rule ad-nauseam, all types inherit from object once and once only - since at the bottom of the hierarchy must be a type that has no base; and therefore which will implicitly inherit from Object.
As for why these languages/frameworks have this as a feature, I have a few reasons:
1) The clue's in the name 'Object Oriented'. Everything is an object, therefore everything should have 'Object' (or equivalent) at it's core otherwise the design principle would be broken from the get-go.
2) Allows the framework to provide hooks for common operations that all types should/might need to support. Such as hash-code generation, string output for debugging etc etc.
3) It means that you can avoid resorting to nasty type casts that can break stuff - like (((int *)(void*))value) - since you have a nice friendly supertype for everything
There's probably loads more than this - and in the time it's taken me to write this 6 new answers have been posted; so I'll leave it there and hope that better people than I can explain in more detail and perhaps better :)
Regarding the first part of your question, it's how classes receive common properties and methods. It's also how we can have strongly-typed parameters to functions that can accept any object.
Regarding your second question, you simply derive your class from the other class; it will then be a descendant of that class, which is in turn a descendant of Object. There's no conflict.
You have the Object base class because amongst others because the Object class has methods (like, in .NET, GetHashCode(), which contain common functionality every object should have).
Multiple inheritance is indeed not possible, but it is possible to derive class A from class B, because A may not directly derive from Object, but B does, so all classes ultimately derive from Object, if you go far enough in the class' inheritance hierarchy.
Just to compare, let's take a look at a language that doesn't enforce a single root class - Objective-C. In most Objective-C environments there will be three root classes available (Object, NSObject and NSProxy), and you can write your own root class by just not declaring a superclass. In fact Object is deprecated and only exists for legacy reasons, but it's informative to include it in this discussion. The language is duck typed, so you can declare a variable's type as "any old object" (written as id), then it doesn't even matter what root class it has.
OK, so we've got all of these base classes. In fact, even for the compiler and runtime libraries to be able to get anywhere they need some common behaviour: the root classes must all have a pointer ivar called isa that references a class definition structure. Without that pointer, the compiler doesn't know how to create an object structure, and the runtime library won't know how to find out what class an object is, what its instance variables are, what messages it responds to and so forth.
So even though Objective-C claims to have multiple root classes, in fact there's some behaviour that all objects must implement. So in all but name, there's really a common primitive superclass, albeit one with less API than java.lang.Object.
N.B. as it happens both NSObject and NSProxy do provide a rich API similar to java.lang.Object, via a protocol (like a Java interface). Most API that claims to deal with the id type (remember, that's the "any old object" type) will actually assume it responds to messages in the protocol. By the time you actually need to use an object, rather than just create it with a compiler, it turns out to be useful to fold all of this common behaviour like equality, hashing, string descriptions etc. into the root class.
Well multiple inheritance is a totally different ball game.
An example of multiple inheritance:-
class Root
{
public abstract void Test();
}
class leftChild : Root
{
public override void Test()
{
}
}
class rightChild : Root
{
public override void Test()
{
}
}
class leafChild : rightChild, leftChild
{
}
The problem here being leafChild inherits Test of rightChild and leftChild. So a case of conflicting methods. This is called a diamond problem.
But when you use the object as super class the hierarchy goes like this:-
class Object
{
public abstract void hashcode();
//other methods
}
class leftChild : Object
{
public override void hashcode()
{
}
}
class rightChild : Object
{
public override void hashcode()
{
}
}
So here we derive both classes from Object but that's the end of it.
It acts like a template for all the objects which will derive from it, so that some common functionality required by every object is provided by default. For example cloning, hashcode and object locking etc.

Why we use inner classes?

I want to ask you why we need inner classes and why we use them ?
I know how to use inner classes but I don't know why..
Some inner classes are exposed publicly (eg Map.Entry in Java) but that is by far the exception rather than the norm.
Inner classes are, basically, an implementation detail.
For example, Swing makes extensive use of inner classes for event listeners. Without them you would end up polluting the global namespace with a bunch of classes you otherwise don't need to see (which may make their purpose harder to determine).
Essentially inner classes are a form of scope. Package access hides classes from outside the package. Private inner classes hide that class from outside that class.
Inner classes in Java are also a substitute for a lack of function pointers or method delegates (which are in C#) or closures. They are the means of passing a function to another function. For example, in the Executor class you have:
void execute(Runnable r);
so you can pass a method in. In C/C++ that could be achieved with:
void execute(void (*run)());
being a pointer to a function.
This piece from wikipedia might help you understand why we need an inner class:
An instance of a normal or top-level class can exist on its own. By contrast, an instance of an inner class cannot be instantiated without being bound to a top-level class.
Let us take the abstract notion of a Car with four wheels. Our wheels have a specific feature that relies on being part of our Car. This notion does not represent the wheels as wheels in a more general form that could be part of vehicle. Instead it represents them as specific to this one. We can model this notion using inner classes as follows:
We have the top-level class Car. Instances of Class Car are composed of four instances of the class Wheel. This particular implementation of Wheel is specific to the car, so the code does not model the general notion of a Wheel which would be better represented as a top-level class. Therefore, it is semantically connected to the class Car and the code of Wheel is in some way coupled to its outer class.
Inner classes provide us with a mechanism to accurately model this connection. We say that our wheel class is Car.Wheel, Car being the top-level class and Wheel being the inner class.
Inner classes therefore allow for the object orientation of certain parts of the program that would otherwise not be encapsulated into a class.
Anonymous inner classes in Java are a way to use the adapter pattern.
interface Bar
{
public void bar();
}
class Foo
{
public void foo()
{
// do something relevant
}
// it happens that foo() defines the same contract (or a compatible one) as
// Bar.bar(); with an anonymous inner class we can adapt Foo to the Bar
// interface
public Bar asBar()
{
// return an instance of an anonymous inner class that implements
// the Bar inteface
return new Bar()
{
public void bar()
{
// from an inner class, we can access the enclosing class methods
// as the "this pointers" are "linked"
foo();
}
};
}
}
In Java, make sure you understand the difference between inner classs and nested class:
an inner class is associated with an
instance of its enclosing class and
has direct access to that object's
methods and fields
C# doesn't have inner classes in sense of Java, only nested classes.
See also this Inner Class Example.
Most of the time I use inner classes is because inner classes are the closest thing to the concept of closure available in other languages. This enables creating and working with an object of inner nested scope which has access to variables of its outer scope. This is often useful in creating callbacks (e.g. defining various Listeners in Swing) among other things.
I use them to scope, for example, if I have the class ebook and I have ebookPrice, I enclose ebookPrice between the ebook class, as it is related to it and only usable (at least conceptually) inside it.
ebookPrice may inherit from Price which is in a more higher scope, and related to every other class.
(Just my two cents).
There are languages that take inner classes to quite some different level, like Beta and Newspeak. In these languages the nesting of classes serves as packaging (ie there are no packages).
For a good coverage of this vision, please refer to "How many concepts for modules do we need?" on the object teams blog. See also the work by Gilad Bracha on his blog...
The object-oriented advantage
In my humble opinion, the most important feature of the inner class is that it allows you to turn things into objects that you normally wouldn't turn into objects. That allows your code to be even more object-oriented than it would be without inner classes.
Let's look at the member class. Since its instance is a member of its parent instance, it has access to every member and method in the parent. At first glance, this might not seem like much; we already have that sort of access from within a method in the parent class. However, the member class allows us to take logic out of the parent and objectify it. For example, a tree class may have a method and many helper methods that perform a search or walk of the tree. From an object-oriented point of view, the tree is a tree, not a search algorithm. However, you need intimate knowledge of the tree's data structures to accomplish a search.
An inner class allows us to remove that logic and place it into its own class. So from an object-oriented point of view, we've taken functionality out of where it doesn't belong and have put it into its own class. Through the use of an inner class, we have successfully decoupled the search algorithm from the tree. Now, to change the search algorithm, we can simply swap in a new class. I could go on, but that opens up our code to many of the advantages provided by object-oriented techniques.
The organizational advantage
Object-oriented design isn't everyone's thing, but luckily, inner classes provide more. From an organizational point of view, inner classes allow us to further organize our package structure through the use of namespaces. Instead of dumping everything in a flat package, classes can be further nested within classes. Explicitly, without inner classes, we were limited to the following hierarchy structure:
package1
class 1
class 2
...
class n
...
package n
With inner classes we can do the following:
package 1
class 1
class 2
class 1
class 2
...
class n
Used carefully, inner classes can provide a structural hierarchy that more naturally fits your classes.
The callback advantage
Inner member classes and anonymous classes both provide a convenient method for defining callbacks. The most obvious example relates to GUI code. However, the application of the callback can extend to many domains.
Most Java GUIs have some kind of component that instigates an actionPerformed() method call. Unfortunately, most developers simply have their main window implement ActionListener. As a result, all components share the same actionPerformed() method. To figure out which component performed the action, there is normally a giant, ugly switch in the actionPerformed() method.
Here's an example of a monolithic implementation:
public class SomeGUI extends JFrame implements ActionListener {
protected JButton button1;
protected JButton button2;
//...
protected JButton buttonN;
public void actionPerformed(ActionEvent e) {
if (e.getSource() == button1) {
// do something
} else if (e.getSource() == button2) {
//... you get the picture
}
}
}
Whenever you see switches or large if/if else blocks, loud alarm bells should begin to ring in your mind. In general, such constructs are bad object-oriented design since a change in one section of the code may require a corresponding change in the switch statement. Inner member classes and anonymous classes allow us to get away from the switched actionPerformed() method.
Instead, we can define an inner class that implements ActionListener for each component to which we want to listen. That may result in many inner classes. However, we can avoid large switch statements and have the added bonus of encapsulating our action logic. Moreover, that approach may improve performance. In a switch where there are n comparisons, we can expect n/2 comparisons in the average case. Inner classes allow us to set up a 1:1 correspondence between the action performer and the action listener. In a large GUI, such optimizations can make a substantial impact on performance. An anonymous approach may look like this:
public class SomeGUI extends JFrame {
// ... button member declarations ...
protected void buildGUI() {
button1 = new JButton();
button2 = new JButton();
//...
button1.addActionListener(
new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent e) {
// do something
}
});
// .. repeat for each button
}
}
Using inner member classes, the same program would look like this:
public class SomeGUI extends JFrame
{
... button member declarations ...
protected void buildGUI()
{
button1 = new JButton();
button2 = new JButton();
...
button1.addActionListener(
new java.awt.event.ActionListener()
{
public void actionPerformed(java.awt.event.ActionEvent e)
{
// do something
}
}
);
.. repeat for each button
Since inner classes have access to everything in the parent, we can move any logic that would have appeared in a monolithic actionPerformed() implementation to an inner class.
I prefer to use member classes as callbacks. However, that is a matter of personal preference. I just feel that too many anonymous classes clutter code. I also feel that anonymous classes can become unwieldy if they are larger than one or two lines.
Disadvantages?
As with anything else, you have to take the good with the bad. Inner classes have their disadvantages. From a maintenance point of view, inexperienced Java developers may find the inner class difficult to understand. The use of inner classes will also increase the total number of classes in your code. Moreover, from a development point of view, most Java tools come up a bit short on their support of inner classes. For example, I use IBM's VisualAge for Java for my day-to-day coding. While inner classes will compile within VisualAge, there is no inner class browser or template. Instead, you must simply type the inner class directly into the class definition. That unfortunately makes browsing the inner class difficult. It is also difficult to type since you lose many of VisualAge's code completion aids when you type into the class definition or use an inner class

Categories

Resources