I'm using GeneralPath to keep track of my game entity's bounds. Unfortunately, it doesn't give me direct access to the points it traverses.
So, I've decided to try and extend one of the Path2D classes, but I've run into issues. Path2D is abstract, and I'd have to add in all the abstract methods, Path2D.Double has all final methods, so I can't override lineTo(x,y) like I wanted, and GeneralPath is final itself.
Is there any way I can make this work? All I want to do is override lineTo(x,y), to update an ArrayList of Point2Ds in the extended class.
Also, please let me know if I misinterpreted something. Polymorphism isn't my strongest area.
You can’t extend from Path2D not because it is final, but because it hasn’t got an accessible constructor.
You can’t override any of the methods of the static subclasses because they are all final. Because they are nested classes, they can gain access even to private constructors.
Can you follow the dictum (possibly from the Gang of Four book) “Favour composition over inheritance”? Create a wrapper class, all the methods of the path object being mirrored in the wrapper. You might have to create a getPath method which returns the path object for painting.
Your wrapper class methods can simply pass messages on to the path object, or add data to a List, as required.
Don’t know whether that will solve your problem, but it might be worth a try.
That is what I ended up doing, which wasn't a terrible way to do it. It got the job done just fine.
But what still confuses me is why the developers down at Oracle would make any of the classes included with Java final.
I know I've heard the reasons to be "security" and "efficiency", but what damage does it do allowing the public to create custom versions of a class?
Seems silly to me.
Why declare a class final? Let's look at the standard example, namely java.lang.String.
The way that String is written, a String object represents a sequence of characters. But not only that: the sequence of characters can't be changed. It's what we call "immutable". This is an extremely important feature; imagine having a reference to a string and finding out that some other code could change that string's value. It would make programming with strings much harder.
Now suppose you could subclass String. Although String doesn't have any methods which allow its contents (the sequence of characters) to be changed, your subclass could conceivably implement such a method. And that would be bad news, because now my String objects might actually be instances of your mutable subclass of String.
So that's one reason why String is final. And in general if you didn't write your class in the expectation that it could be subclassed, you really ought to declare it final, otherwise people could write subclasses which violate your class's original contract.
I understand the logic behind this setup, but I can't think of a situation where this would happen.
This is an extremely important feature; imagine having a reference to a string and finding out that some other code could change that string's value. It would make programming with strings much harder.
What would be "some other code"? Some code that a developer working on the same project might have?
I'm still a bit lost at this notion. Could you give an example that shows the consequences?
Also, why would changing a String Object's value be such a disaster when changing some other Object's value is something that we often do?
Thanks for being patient.
I'm always stubborn when learning something new.
Thanks for the direction
This is exactly what I've been looking for to clarify some of the questions I have concerning objects.
But I won't be satisfied till I've read it all!
posted 7 years ago
When we start out learning programming, particularly object‑oriented programming, we are told all about inheritance. What we don’t find out until later is that inheritance is difficult to implement. You end up violating immutability, breaching the general contract of the equals method, not fulfilling the Liskov Substitution Principle, and having to use awkward down‑casts to use all the features of subclasses, if you don’t use inheritance correctly and carefully. So you end up with things like the chapter in Effective Java about Document for Inheritance or Prohibit It (or similar). Paul C is right, that when you have a class the way you want it, it is a good idea to make it un‑inheritable‑from.
posted 7 years ago
Caleb Kemper wrote: . . . But I won't be satisfied till I've read it all! . . .
Quite right. Read the article and understand it, then you will know so much more. That is the way to learn.
posted 7 years ago
Find Effective C++ §35 for two examples where simple inheritance can fall down disastrously.
Campbell Ritchie wrote:What we don’t find out until later is that inheritance is difficult to implement.
And as Campbell also said earlier in the thread, inheritance is often the wrong thing to do anyway. "Prefer composition to inheritance" was the quote.
My basic rule of thumb these days is that if I'm going to have B inheriting from A, then at some point I should have code which looks like "A value = new B()", in other words code which treats a B object as if it were of type A.