Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

To clarify, what I'm asking about is

public class A{
    private/*or public*/ B b;
}

vs.

public class A{
    private/*or public*/ class B{
        ....
    }
}

I can definitely think of some reasons to use one or the other, but what I would really like to see are convincing examples that show that the pros and cons are not just academic.

share|improve this question
2  
The answer would depend on the facilities provided by the language and core libraries. Assuming C# language, try to run these by StyleCop. I am pretty sure that you will get a warning about separating this class out into its own file. That means that enough people at MSFT think that you do not need to use either one of the examples that you have used. –  Job Jun 5 '11 at 1:58
    
What would a convincing example be, if academic examples are not good enough? –  user1249 Sep 11 '12 at 8:58

9 Answers 9

up vote 13 down vote accepted

They are typically used when a class is an internal implementation detail of another class rather than a part of its external interface. I've mostly seen them as data-only classes that make the internal data structures cleaner in languages that don't have a separate syntax for c-style structs. They are also useful sometimes for highly customized, one-method derived objects like event handlers or worker threads.

share|improve this answer
2  
This is how I use them. If a class is, from a functional point of view, nothing but a private implementation detail of another class, then it should be declared that way, just as a private method or field would be. No reason to pollute the namespace with garbage that's never going to get used elsewhere. –  Aaronaught Jun 5 '11 at 3:32
  • Inner classes in some language (Java for instance) have a tie to an object of their containing class and may use their members without qualifying them. When available, it is clearer than reimplementing them using other language facilities.

  • Nested classes in other language (C++ for instance) don't have such tie. You are simply using the scoping and accessibility control provided by the class.

share|improve this answer
3  
Actually Java has both of those. –  Joachim Sauer Sep 11 '12 at 7:17

In my opinion it's a fair cop to use internally-defined classes for classes that are used briefly in a class to allow a specific task.

For example, if you need to bind a list of data consisting of two unrelated classes:

public class UiLayer
{
    public BindLists(List<A> as, List<B> bs)
    {
        var list = as.ZipWith(bs, (x, y) => new LayerListItem { AnA = x, AB = y});
        // do stuff with your new list.
    }

    private class LayerListItem
    {
        public A AnA;
        public B AB;
    }
}

If your internal class is used by another class you should put it separate. If your internal class contains any logic, you should put it separate.

Basically, I think they're great for plugging holes in your data objects, but they're difficult to maintain if they have to actually contain logic, since you'll have to know where to look for them if you need to change it.

share|improve this answer
2  
Assuming C#, can't you just use tuples here? –  Job Jun 5 '11 at 1:56
3  
@Job Sure, but sometimes the tuple.ItemX makes the code unclear. –  Lasse Espeholt Jun 5 '11 at 9:52
2  
@Job yup, lasseespeholt got that one right. I'd rather see an inner class of { string Title; string Description; } than a Tuple<string, string>. –  Ed Woodcock Jun 5 '11 at 10:07
    
at that point would not it make sense to put that class into its own file? –  Job Jun 5 '11 at 19:03
    
Nope, not if you're only really using it to tie some data together briefly to achieve a task that doesn't go outside of the remit of the parent class. At least, not in my opinion! –  Ed Woodcock Jun 5 '11 at 19:25

I avoid inner classes in Java because hot-swapping doesn't work in the presence of inner classes. I hate this because I really hate to compromise the code for such considerations, but those Tomcat restarts add up.

share|improve this answer
    
is this issue documented somewhere? –  gnat Sep 11 '12 at 8:21
    
Downvoter: is my assertion incorrect? –  kevin cline Sep 11 '12 at 16:20
1  
I downvoted because your answer lacks details, not because it is incorrect. Lack of details makes your assertion hard to verify. If you add more on that issue, I would likely revert to upvote, because your information looks pretty interesting and may be useful –  gnat Sep 12 '12 at 6:29
1  
@gnat: I did a little research and while this seems to be a well-known truth, I did not find a definitive reference on the limitations of Java HotSwap. –  kevin cline Sep 12 '12 at 14:10
    
we're not on Skeptics.SE :) just some reference would do, it needn't be definitive –  gnat Sep 12 '12 at 14:48

Suppose you're building a tree, a list, a graph and so on. Why should you expose the internal details of a node or a cell to the external world?

Anyone using a graph or a list should only rely on its interface, not its implementation, since you may want to change it one day in the future (e.g. from an array-based implementation to a pointer-based one) and the clients using your data structure (each one of them) would have to modify their code in order to adequate it to the new implementation.

Instead, encapsulating the implementation of a node or a cell in a private inner class gives you the freedom to modify the implementation any time you need to, without the clients to be forced to adjust their code consequently, as long as your data structure's interface remains untouched.

Hiding the details of your data structure's implementation also leads to security advantages, because if you want to distribute your class you'll make only the interface file available together with the compiled implementation file and nobody will know if you're actually using arrays or pointers for your implementation, thus protecting your application from some kind of exploitation or, at least, knowledge due to the impossibility to misuse or inspect your code. In addition to practical issues, please do not underestimate the fact that it's an extremely elegant solution in such cases.

share|improve this answer

One reason to use a private inner class might be because an API you're using requires inheritance from a particular class, but you don't want to export the knowledge of that class to users of your outer class. For example:

// async_op.h -- someone else's api.
struct callback
{
    virtual ~callback(){}
    virtual void fire() = 0;
};

void do_my_async_op(callback *p);



// caller.cpp -- my api
class caller
{
private :
    struct caller_inner : callback
    {
        caller_inner(caller &self) : self_(self) {}
        void fire() { self_.do_callback(); }
        caller &self_;
    };

    void do_callback()
    {
        // Real callback
    }

    caller_inner inner_;

public :
    caller() : inner_(*this) {}

    void do_op()
    {
        do_my_async_op(&inner_);
    }
};

In this, the do_my_async_op requires an object of type callback to be passed to it. This callback has a public member function signature that the API uses.

When do_op() is called from the outer_class, it uses an instance of the private inner class which inherits from the required callback class instead of a pointer to itself. The outer class has a reference to the outer class for the simple purpose of shunting the callback into the outer class's private do_callback member function.

The benefit of this is that you are sure that no-one else can possibly call the public "fire()" member function.

share|improve this answer

Private and inner classes are used to increase levels of encapsulation and hide implementation details.

In C++, in addition to a private class, the same concept can be achieved by implementing a class cpp's anonymous namespace. This serves nicely to hide/privatize an implementation detail.

It is the same idea as an inner or private class but at an even greater level of encapsulation as it is completely invisible outside the file's compilation unit. Nothing of it appears in the header file or is outwardly visible in the class's declaration.

share|improve this answer
    
Any constructive feedback on the -1? –  hiwaylon Sep 11 '12 at 12:57
1  
I didn't downvote but I would guess that you are not really answering the question: you are not giving any reason to use private/inner class. You are just describing how it works and how to do a similar thing in c++ –  Simon Sep 11 '12 at 15:19
    
Indeed. I thought it was obvious by mine and the other answers (hiding implementation details, increased levels of encapsulation, etc) but I'll try to clarify some. Thanks @Simon. –  hiwaylon Sep 11 '12 at 19:40
1  
Nice edit. And please do not take offense because of this kind of reaction. The SO network is trying to enforce policies to improve the signal to noise ratio. Some people are pretty strict about question/answer scope, and sometime forget to be nice (by commenting their downvote for example) –  Simon Sep 12 '12 at 7:44
    
@Simon Thanks. It is dissapointing because of the poor communication quality it exhibits. Maybe it is a little too easy to be "strict" behind the anonymous veil of the web? Oh well nothing new I guess. Thanks again for the positive feedback. –  hiwaylon Sep 13 '12 at 0:58

According to Jon Skeet in C# in Depth, using a nested class was the only way to implement a fully lazy thread-safe singleton (see Fifth Version) (until .NET 4).

share|improve this answer
    
it's Initialization On Demand Holder idiom, in Java it also requires private static inner class. It's recommended in JMM FAQ, by Brian Goetz in JCiP 16.4 and by Joshua Bloch in JavaOne 2008 More Effective Java (pdf) "For High-Performance on a Static Field..." –  gnat Sep 12 '12 at 7:07

One of uses for private static inner class is Memo pattern. You put all data that needs to be remembered into private class and return it from some function as Object. Noone outside cannot (without reflection, deserialization, memory inspection ...) look into it/modify it, but he can give it back to your class and it can restore its state.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.