views:

78

answers:

3

I use the Scanner class for reading multiple similar files. I would like to extend it to make sure they all use the same delimiter and I can also add methods like skipUntilYouFind(String thisHere) that all valid for them all.

I can make a utility-class that contain them, or embed the Scanner Class as a variable inside another class but this is more cumbersome.

I have found some reasons to declare a class final, but why is it done here?

+1  A: 

Probably because extending it and overwriting some of it's methods would probably break it. And making it easier to overwrite methods would expose to much of the inner workings, so if in the future they decide to change those (for performance or some other reasons), it would be harder for them to change the class without breaking all the classes that extend it.

For example, consider the following method in the class:

public boolean nextBoolean()  {
    clearCaches();
    return Boolean.parseBoolean(next(boolPattern()));
}

Say you want to overwrite this because you want to make 'awesome' evaluate to a 'true' boolean (for whatever reason). If you overwrite it, you can't call super.nextBoolean(), since that would consume the next token using the default logic. But if you don't call super.nextBoolean(), clearCaches() won't be called, possibly breaking the other not overwritten methods. You can't call clearCaches() because it's private. If they made it protected, but then realized that it's causing a performance problem, and wanted a new implementation that doesn't clear caches anymore, then they might break your overwritten implementation which would still be calling that.

So basically it's so they can easily change the hidden parts inside the class, which are quite complex, and protecting you from making a broken child class (or a class that could be easily be broken).

Andrei Fierbinteanu
That would explain why the function nextBoolean should be defined as 'final public boolean nextBoolean()', not the whole class?
Roalt
Yeah, but you could have a method that doesn't have clearCaches() in it, and it's not declared final, but they realize that they need to add clearCaches() there as well, but now they can't declare it final (since it would break classes extending it). And a lot (if not all of the methods) rely a lot on the hidden implementation anyway (a lot of them would have to be final from the start). It's just easier, and makes more sense to declare the whole thing final (since the parts that should be final could change on changing the inner implementation).
Andrei Fierbinteanu
A: 

I think that the link you provided explains it all.

In your case it seems like you should prefer composition instead of inheritance anyway. You are creating a utility that has some predefined behavior, and that can hide some (or all) of the details of the Scanner class.

I've seen many implementations that used inheritance in order to change a behavior. The end result was usually a monolithic design, and in some cases, a broken contract, and/or broken behavior.

Eran Harel
Making it a composition will increase the size of my code. It's not a sin, but you will get my.scanner.next() (or even my.getScanner().next() instead of my.next(). I think it's less beautiful, right? And it's less "replace this" by "that"...
Roalt
Well, if you have to yourObject.scanner.next() then that's not encapsulation right? But if you have a yourObject.process(input) : returnVal then you do.
Eran Harel
A: 

I suppose it is due to security reasons. This class reads user input, so that someone with bad intentions could extend it, modify it's behavior and you'd be screwed. If it is final, it is not that easy for the bad guy, because if he makes his own type of Scanner (not java.util.Scanner), the principles of Polymorphism would be broken. See the bad guy can be smart enough to write a bot/script which does this automatically on remote servers... He can even do it by dynamic classloading in compiled application.

lisak