Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Downcasting a Graphics instance - Why is it allowed?

I'm trying to figure out why it is allowed to downcast a Graphics instance to a Graphics2D instance.

It's usually against the rules to downcast a reference type that isn't inheriting the target type.

In the graphic-oriented classes the hierarchy is like the following:

  1. Graphics is the superclass
  2. Graphics2D is the subclass of the superclass Graphics

When drawing something in Swing you override the paint() method - And if you're in need of 2D-drawing you downcast the automatically supplied Graphics instance from the paint() method to a Graphics2D instance:

public void paint(Graphics g)
{
    super.paint(g);

    Graphics2D g2d = (Graphics2D)g;
}

But this is reverse? A Graphics instance is NOT inheriting a graphics2D instance - It's the Graphics2D instance that IS inheriting a Graphics instance when looking at the class-hierarchy!

Why is this allowed?

like image 515
Birdman Avatar asked Dec 26 '22 00:12

Birdman


2 Answers

Graphics2D is a class which inherits from Graphics - the same way that "human" is a class of "biped", and it is true that all humans are bipeds but it is not true that all bipeds are humans.

java.awt.Graphics dates to the earliest days of Java and was not very sophisticated. Waphen Swing and Java2D were created, Graphics2D was created as a subclass of Graphics so that old code would work - backwards compatibility was a religion at Sun (and not a bad one).

JComponent and other Swing classes inherit from java.awt.Component, which used the old API. To make it easy for people to migrate from AWT to Swing without making any changes except the superclass, Swing kept the signature of taking a Graphics rather than a Graphics2D.

It is well documented that in Swing, the Graphics passed to paint(Graphics) will always be a Graphics2D, so you do not need an alternate code-path to handle the case that it is not.

like image 127
Tim Boudreau Avatar answered Jan 08 '23 10:01

Tim Boudreau


It's allowed if you know that g will indeed be an instance of Graphics2D at runtime. If it is not, you will get a ClassCastException at runtime.

If you check the documentation for Graphics, you will note that there are only two known subclasses of Graphics, Graphics2D and DebugGraphics. So, barring a custom implementation of a Graphics subclass, you can be fairly certain you're dealing with a Graphics2D instance.

like image 36
GriffeyDog Avatar answered Jan 08 '23 10:01

GriffeyDog