Downcasting instance of Graphics - Why is it allowed?

I am trying to understand why it is allowed to omit the Graphics instance on the Graphics2D instance.

As a rule, omit a reference type for rules that does not inherit the target type .

In graphically oriented classes, the hierarchy is as follows:

  • Graphics is a superclass
  • Graphics2D is a subclass of the Graphics superclass.

When you draw something in Swing, you override the paint () method. And if you need a 2D drawing, you drop the automatically provided Graphics instance from the paint () method into the Graphics2D instance:

public void paint(Graphics g) { super.paint(g); Graphics2D g2d = (Graphics2D)g; } 

But is it the other way around? The Graphics instance does NOT inherit the graphics2D instance. This is a Graphics2D instance that IS inherits from the Graphics instance when viewing the class hierarchy!

Why is this allowed?

+4
source share
7 answers

Graphics2D is a class that inherits from Graphics - the same way that “man” is a “two-legged” class, and it’s true that all people are two-legged, but it’s not that all two-legged people are human.

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

JComponent and other Swing classes inherit from java.awt.Component that used the old API. To make it easier for people to switch from AWT to Swing without making any changes other than the superclass, Swing saved the signature by taking Graphics , not Graphics2D .

It is well known that in Swing, the graphics passed to paint(Graphics) will always be Graphics2D , so you don’t need an alternative code path to handle what is not.

+2
source

This is allowed if you know that g will indeed be an instance of Graphics2D at runtime. If this is not the case, you will get a ClassCastException at runtime.

If you check the documentation for Graphics , you'll notice that there are only two well-known subclasses of Graphics , Graphics2D and DebugGraphics . Thus, by disallowing your own implementation of the Graphics subclass, you can be pretty sure that you are dealing with an instance of Graphics2D .

+3
source

Graphics is the superclass of Graphics2D. As to why this actor is needed, I'm not sure. This is what bothers me too.

Edit:

Check this:

Graphics2D was introduced after JDK 1.1. I think we need to compress Graphics to Graphics2D in order to maintain backward compatibility with legacy programs.

If you need access to more advanced features that you passed in Graphics2D. This violates best practices, but is probably believed to support backward compatibility.

+1
source

The object that is passed to the paint method is of type Graphics2D. You, as a programmer, know this, even if it is not explicit in the method signature (because in general it is not necessary). Thus, he is allowed to discard the object.

+1
source

You are confused Graphics is a superclass from Graphics2D. You can downgrade, but downcasting dangereous is better to use instanceof to avoid a ClassCastException runtime ClassCastException .

Also, do not override paint unless you need to override paintComponent instead.

+1
source

Sometimes downcasting is useful because the data comes from code that cannot know its actual type. Consider this example from the Hibernate interceptor interface

 public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) { // do nothing } 

Note that entity is typed as Object , although this is by far the more specific type. Hibernate may not have a compilation reference for the types of objects it stores, but this can still be a useful method:

 if (entity instanceof Auditable) { Auditable data = (Auditable)entity; // downcast logger.warn("{current user} is deleting " data.GetDescriptionForAudit()); } 

In this example, casting is inevitable - the Hibernate API cannot be improved, Object is the best type that can be used.

In the case of the swing paint method, it seems that the method signature was supposed to use Graphics2D , otherwise the methods you needed should be defined in the Graphics class. Perhaps the swing designers are trying to say "not dependent on Graphics2D methods if you really need it."

To answer the question

Downcasting is allowed because sometimes a programmer has to do this. In the Hibernate example, the API is typed as well as it can be. In the swing example, it can be argued that the API has a flaw. But in any case, it is useful for Java to allow downcasting.

+1
source

In fact, Graphics2D is a subclass of Graphics. When we pass an instance of graphics as an argument, say ( Graphics g ), then g declared internally as follows: g = new Graphics2D . Since Graphics2D is a subclass of graphics. Therefore, g now an instance of Graphics 2D with the datatype of graphics.Therefore , we can reset g to Graphics 2D .

0
source

Source: https://habr.com/ru/post/1490990/


All Articles