File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes Beginning Java and the fly likes Restricting Sub-class declaration Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Restricting Sub-class declaration" Watch "Restricting Sub-class declaration" New topic
Author

Restricting Sub-class declaration

Swaranga Sarma
Greenhorn

Joined: Dec 17, 2010
Posts: 9
I have an application where I want all my model classes to implement a specific update method. For this I created an abstract class and an interface with the following declaration:



Hence all my model classes will extend BaseClass. For example a Book class definition will be



However using the above construct I am not able to restrict declarations of my model classes. For example while it is valid and required for the Book class to extend BaseClass<Book>, the following declaration also valid:



Here User is also a model class. While it is syntactically correct to do the above I want to restrict that.

Basically I want my model classes' update method to take as parameter an instance of its own class and return an instance of its own class and nothing else.

In other words, if there is a class C that extends BaseClass, then its update method must be of the exact signature C update(C c).

Or in other words if there is a class C that extends BaseClass, then the template parameter for BaseClass must be C itself [ie C extends BaseClass<C>] and nothing else.

How do I achieve that?

NOTE: This is somewhat similar to the enum declaration



Here we are able to restrict the definition of compareTo method to take an instance of its own type of enum and not any other kind of enum.

Thanks in advance.
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3611
    
  14

Why would you want to?

An interface describes what its implementing classes should be able to do. Why should it care about how they do it? What reason could you have to restrict the usefulness of the subclassing mechanism?
Swaranga Sarma
Greenhorn

Joined: Dec 17, 2010
Posts: 9
Like I said, I want my model classes to override the update method with the exact signature of C update(C c). For example if there is a class Book and the coder extends BaseClass, the the update method must be of the exact signature Book update(Book b). This is similar to the enum declaration where the compareTo method is restricted to take as parameter enums of only that same class type and not any other enum.

Basically the developer writing a model class Book and extending BaseClass must not be able to extend the BaseClass in anyway other than the following syntax : Book extends BaseClass<Book>. Any other type other than Book must be invalid.
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

Then the easiest solution would be to not use generics and to hard-code Book in the place where you only want people to use "Book".
Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3611
    
  14

Swaranga Sarma wrote:Any other type other than Book must be invalid.

Yes yes, but *why*?

What do you gain from making it invalid?
Luigi Plinge
Ranch Hand

Joined: Jan 06, 2011
Posts: 441

I think a more general question along the same lines would be "is it possible to restrict what classes will implement a given interface?" I think the answer is "no".

Perhaps the reason for this is that it wouldn't be very useful. For example, we can't write general methods for BaseInterface: it has to be parameterized. (Well, you can, but the argument type would be Object, which is not useful.) Even then, the only method you'll have available is "update".

I would be interested if you could come up with a concrete example of where this model would be useful - and if you find a solution to your problem, keep us updated!
Swaranga Sarma
Greenhorn

Joined: Dec 17, 2010
Posts: 9
A valid scenario would somewhat similar to the be the enum declaration and comparison. Suppose we have declared an enum Priority as follows



and another enum Severity



Now it is invalid to compare one enum from another. For example, the following would result in a compiler error:



Similarly, if there are two model classes in my application, Book and User; and both extend BaseClass<Something> then it must be invalid to do either of the following:



or



The above two would be possible if the developer codes his classes as follows [which I do not want]:


Stephan van Hulst
Bartender

Joined: Sep 20, 2010
Posts: 3611
    
  14

You still have not explained why you want to restrict this. If Book wants to update using a User, or vice versa, then why should your interface care? If you want Book to use a Book, then you should write Book properly.

A supertype should not care about whether its children misbehave.
Swaranga Sarma
Greenhorn

Joined: Dec 17, 2010
Posts: 9
Stephan van Hulst wrote:You still have not explained why you want to restrict this. If Book wants to update using a User, or vice versa, then why should your interface care? If you want Book to use a Book, then you should write Book properly.

A supertype should not care about whether its children misbehave.


I think I get your point. So you are saying that I should not care if the Book class updates itself using a User class? I was under the impression that it would be conceptually incorrect to allow so.

But can I at least restrict the return type to be at least of the Book type [for the update method of a Book class], such that no matter what type is used for update, the return type is always the same class type itself. For example for a model class C the update method must be


Can this be achieved, or is it that this too is too much of a restriction on the subclasses?
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19670
    
  18

I wouldn't change your original code. Those Book and User classes are just fine. The only "problem" is that someone can write a class UserBook that extends BaseClass<User> instead of BaseClass<Book>, but as said you shouldn't care about that as long as the method is implemented correctly according to its specification.


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Luigi Plinge
Ranch Hand

Joined: Jan 06, 2011
Posts: 441

Swaranga - I'm just wondering how the Enum example that you give is any different? Couldn't you have two classes extending that which can compare each other? Perhaps for enumerations using the enum keyword, it's implemented in a way that can't be achieved through the Java language.

By the way, your example is an example of bounded quantification, specifically recursively-bounded quantification, which may be a good lead if you want to read up further. I can't see any mention of the ability to restrict to a single specific type though.

A similar idea is of covariant vs invariant vs contravariant subtyping, which determines whether or not A<Y> is a subtype of A<X>, if Y extends X. I don't think you can do this in Java, although you can in Scala (if you're interested see here). You might like to ask a question on Stackoverflow.com - particularly if you give it a Scala as well as a Java tag, and ask "if not possible in Java, is it in Scala", you will certainly get answers from world experts in the subject.
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19670
    
  18

Luigi Plinge wrote:Swaranga - I'm just wondering how the Enum example that you give is any different? Couldn't you have two classes extending that which can compare each other? Perhaps for enumerations using the enum keyword, it's implemented in a way that can't be achieved through the Java language.

1) You can't manually extend java.lang.Enum, only by using the enum keyword.
2) With enums, the implicit X extends Enum<X> enforces that the generic type X matches the class name X.

With regular classes, there is no way to enforce that the generic type matches the class name.
 
 
subject: Restricting Sub-class declaration