aspose file tools*
The moose likes Java in General and the fly likes inner classes and encapsulation Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Java in General
Bookmark "inner classes and encapsulation" Watch "inner classes and encapsulation" New topic
Author

inner classes and encapsulation

Dan Murphy
Ranch Hand

Joined: Mar 29, 2005
Posts: 126
Hi,

If I declare a class named 'Inner' within a class 'Outer', then Outer can access all the members (including private) of Inner. Doesn't this break the principle of encapsulation?

I guess one explanation for this design might be "Inner is a member of Outer, so therefore Outer should have full access to it". However, this is not a sufficient justification (for me). Particularly in the case where Inner is a private class, and can only be used by Outer, the only possible intention that marking a member of Inner as private could have is "Outer can't touch this", but of course it can....

I've almost completely stopped using inner classes (apart from simple Swing listeners) since I discovered this. Am I missing something?

Cheers,
Dan
[ June 04, 2007: Message edited by: Dan Murphy ]

SCJP, SCJD, SCWCD
arulk pillai
Author
Ranch Hand

Joined: May 31, 2007
Posts: 3216
You are on the right track.


Where should you use inner classes?

Code without inner classes is more maintainable and readable.

When you access private data members of the outer class, the JDK compiler creates package-access member functions in the outer class for the inner class to access the private members. This leaves a security hole.

In general we should avoid using inner classes. Use inner class only when an inner class is only relevant in the context of the outer class and/or inner class can be made private so that only outer class can access it. Inner classes are used primarily to implement helper classes like Iterators, Comparators etc which are used in the context of an outer class.


Java Interview Questions and Answers Blog | Amazon.com profile | Java Interview Books
Dan Murphy
Ranch Hand

Joined: Mar 29, 2005
Posts: 126
But even when an inner class (such as an Iterator) is used in the context of an outer class (such as a Collection), you could achieve the same thing without inner classes by (in this example) passing a reference to the Collection to the constructor of the Iterator.

This gives the Iterator access to the public members of the Collection object - the only members it should need to access - without using inner classes. By the way, is it true that the inner class can access the private members of the outer class (as well as vice versa)? If so, then inner classes are doubly bad
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24166
    
  30

Originally posted by Dan Murphy:

This gives the Iterator access to the public members of the Collection object - the only members it should need to access - without using inner classes.


Well... no. Show me how to write an Iterator over a Map using only the public API. Can't do it, right? The Iterator needs to know about the implementation of the Map. Now, there are various ways to implement this: for example, make the Map implementation's member package-protected, for example, and put the Iterator class in the package with it. You could make a package containing only these two classes.

But if you instead make the Iterator an inner class, then all the members are private, and no code outside of the Map implementation can diddle with it. Seems nicer to me, frankly.

Part of the problem here is that Java doesn't have protected interfaces. If a class implements an interface, all the methods that implement it have to be public. If that weren't the case, a Map implementation could provide an IteratorHelper interface that an Iterator could use. But in Java as it stands, all those methods, which aren't used by normal clients, would be there, public, cluttering up the interface.


[Jess in Action][AskingGoodQuestions]
Pravin Jain
Ranch Hand

Joined: May 20, 2007
Posts: 60
Are you discussing about inner classes or about nested classes?
static member classes are not inner classes.
An inner class (non-static nested class) has can access private
members of enclosing class, as well as vice versa.
The advantage with inner class is that it can also be used to
represent a one to many relationship (something which I have
not found commonly). It also guarantees that the instance of
inner class cannot be created unless there is an instance of
the enclosing class.
eg. one cannot have a Transaction unless there is an instance
of Account and once a Transaction is created with a particular
Account instance then it cannot become Transaction of another
Account. Transaction could an inner class for Account in this case.

The static member classes are like any other class except for
the access restrictions removed between the enclosing class and
the member class. ie. you want to allow some class extra
privileges.
[ June 04, 2007: Message edited by: Pravin Jain ]

The Zen of Java Programming.
Dan Murphy
Ranch Hand

Joined: Mar 29, 2005
Posts: 126
The advantage with inner class is that it can also be used to
represent a one to many relationship (something which I have
not found commonly).

Can you achieve anything by modelling one-to-many relationships in this way that cannot be more simply represented with a class that has a member which is a Collection, array, etc.
It also guarantees that the instance of
inner class cannot be created unless there is an instance of
the enclosing class.
eg. one cannot have a Transaction unless there is an instance
of Account and once a Transaction is created with a particular
Account instance then it cannot become Transaction of another
Account. Transaction could an inner class for Account in this case.

Again, I don't think you need inner classes for this. If the Transaction class takes an Account as it's constructor parameter and stores the argument in a final field, you've achieved the same thing
[ June 04, 2007: Message edited by: Dan Murphy ]
Dan Murphy
Ranch Hand

Joined: Mar 29, 2005
Posts: 126
Part of the problem here is that Java doesn't have protected interfaces. If a class implements an interface, all the methods that implement it have to be public. If that weren't the case, a Map implementation could provide an IteratorHelper interface that an Iterator could use. But in Java as it stands, all those methods, which aren't used by normal clients, would be there, public, cluttering up the interface.

For the sake of discussion, if a class could mark part of it's interface as protected, then how would you define which other classes could access the protected interface? Presumably it wouldn't work the same as the 'protected' scope identifier, because one wouldn't want to force (for example) an Iterator to extend Map in order to access it's protected interface. This would break the "is a" inheritance test. Providing access only to classes in the same package doesn't seem much better, as we'd (again) need to put only the Map and Iterator in the same package in order to allow only the Iterator to access the protected interface.

[ June 04, 2007: Message edited by: Dan Murphy ]
[ June 04, 2007: Message edited by: Dan Murphy ]
Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671
Java does allow a protected nested interface:

This compiles and runs just fine. The interface Bar is only accessible to Foo, subclasses of Foo, and other code in the same package. It's pretty rare that you'd have a use for this, but it's allowed.

However, what EFH probably meant to say is that Java does not allow interface members to be protected:

This doesn't compile. It doesn't matter if Bar is a nested interface or not - the methods inside an interface can never be protected, package, or private. They are implicitly public. It's possible that protected methods in interfaces could have been useful, but they're not allowed.


"I'm not back." - Bill Harding, Twister
Devesh H Rao
Ranch Hand

Joined: Feb 09, 2002
Posts: 687

Originally posted by Dan Murphy:

Can you achieve anything by modelling one-to-many relationships in this way that cannot be more simply represented with a class that has a member which is a Collection, array, etc.


[ June 04, 2007: Message edited by: Dan Murphy ]


Just for an example, I need to store an Identity object in my application. it may vary from a single concanated string to multiple strings from one implementation to another implementation.

The definition of the identity, persistence and display is all specific to Identity and hence is internal to it which should not be accessed by any external class. The example I have shown contains the atomic level definition of Identity contained in a simple Names inner class but it can easily be extended to include identification numbers, prefix, suffix etc.




PS: The code is to give an idea of where 1-N type of relationship may exist in an inner class. The code may not be tuned for correctness so I apologize for the same beforehand.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
In some sense it is true that inner/nested classes "break" encapsulation. The important thing to notice is that there needs to be a balance - a system with "fully encapsulated classes" couldn't do anything, because the classes need a certain amount of coupling to communicate. So the design goal cannot be to *maximize* encapsulation, but to *manage* it.

Some classes are just naturally so strongly coupled to another class - such as the implementation of an Iterator to its Collection class - that it wouldn't give any benefit to encapsulate them from each other.

In fact it could probably be argued that they are so strongly coupled, that it makes sense to encapsulate the knowledge of how the iterator is implemented inside the collection class.

Does that sound reasonable?


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24166
    
  30

Originally posted by Jim Yingst:

However, what EFH probably meant to say is that Java does not allow interface members to be protected:


Yeah, that's the idea, anyway. I think I was using the words "interface" (as in, a set of methods on an object) and "interface" (the Java keyword) both in the same paragraph. If it were possible for HashMap and TreeMap and LinkedHashMap, etc, to implement a "MapIteratorHelper," the methods of which were visible only inside java.util, then you could reasonably implement a MapIterator class as a top-level class without making the data members of those Map classes non-private.
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: inner classes and encapsulation
 
Similar Threads
INNER CLASSES . PLS HELP
inner classes see everything?
wrong explanation in javacertificate exam
innerclasses
Inner Classes