Если абстрактный класс не может быть создан, почему возможно следующее? - PullRequest
0 голосов
/ 05 июля 2019

В следующем коде объект Graphics передается в следующий метод paintComponent, который затем преобразуется в объект Graphics2D. Разве Графика не является абстрактным классом, так почему возможно следующее?

 public void paintComponent(Graphics comp) {
 Graphics2D comp2D = (Graphics2D) comp;
 Font font = new Font("Comic Sans", Font.BOLD, 15);
 comp2D.setFont(font);
 comp2D.drawString("Potrzebie!", 5, 50);
}

Ответы [ 2 ]

2 голосов
/ 05 июля 2019

Тот факт, что класс не может быть создан, не означает, что вы не можете получить его экземпляр.

В вашем примере все, что вы делаете - это приводите его к другому классу, который находится в иерархии Graphics.

Вот пример.


    public class AbstractDemo {

       public static void main(String[] args) {
          Concrete c = new Concrete();
          AClass a = (AClass) c;
          a.me();
       }

    }

    abstract class AClass {
       public void me() {
          System.out.println("Abstract parent");
       }
    }

    class Concrete extends AClass {

    }

0 голосов
/ 05 июля 2019

Класс, являющийся абстрактным, просто означает, что вы не можете создать такой класс напрямую.Если у вас есть такой класс, вы можете привести его к виду, как будто это любой из его подклассов.Другими словами, все «абстрактные» средства - это то, что вы не можете сделать:

SomeAbstractClass obj = new SomeAbstractClass(...);

У вас может быть ссылка на объект Graphics2D, как в вашем примере, но если вы попросите Java сообщитьВы настоящий тип объекта, на самом деле он никогда не будет Graphics2D объектом.Исходя из этого кода, вы не можете быть уверены, что реальный тип рассматриваемого объекта также является Graphics объектом.Это может снова быть ссылкой на подкласс реального объекта, например, может быть MyGraphicsObject или что-то в этом роде.

В этом весь смысл и сила полиморфизма.После создания объекта он будет вести себя как любой из его подклассов и может рассматриваться как чистый экземпляр любого из этих подклассов с помощью апскейтинга.

Вот некоторый код, который указывает, что происходит сидентификатор объекта, который передается вверх:

abstract class Abstract {
    public void whatAmI() {
        System.out.println("I'm Abstract");
    }
}

class Concrete extends Abstract {
    @Override
    public void whatAmI() {
        System.out.println("I'm Concrete");
    }
}

public class X {

    public static void main(String[] args) {

        // This won't compile.  That's what it means for "Abstract" to be abstract.
        // Abstract abs = new Abstract();

        // You can create a Concrete, and then upcast it to an Abstract reference...
        Concrete concrete = new Concrete();
        Abstract abs = (Abstract)concrete;

        // But it's stll really a Concrete
        System.out.println(abs.getClass().getName());

        // And it will still act like a Concrete if Concrete has overridden one of Abstract's methods.
        abs.whatAmI();
    }
}

Результат:

org.littleshoot.proxy.inlet.Concrete
I'm Concrete

Обратите внимание, что если вы спросите у Java тип объекта, он все равно будет конкретным, даже если вы просилитип объекта с помощью абстрактной ссылки.Также обратите внимание, что если вы вызываете метод класса Abstract, который был переопределен в Concrete, будет вызываться версия Concrete.

...