Избегание приведения типов Dynami c с наследованием для классов данных в Java - PullRequest
2 голосов
/ 14 апреля 2020

У меня есть 3 класса данных

@Data
class A
{
    private int a;
}

@Data
class B extends A
{
    private int b;
}

@Data
class C extends A
{
    private int c;
}

Класс B и C имеют некоторые общие поля между ними, которые хранятся в родительском классе A. Ниже приведен класс тестера

class TesterClass
{
    static String bOrC = "C"; // input from some decision
    public static void main(String[] args) // assume this to be the client
    {
        A a;
        if (bOrC.equals("B")) {
            B b = new B();
            b.setB(11);
            a = b;
        } else {
            C c = new C();
            c.setC(12);
            a = c;
        }
        a.setA(10);
        doSomething(bOrC, a);

    }

    // Below are the service methods
    // only this method in the service exposed
    public static void doSomething(String bOrC, A a) {
        if (bOrC.equals("B")) {
            doSomethingWithB(a);
        } else if (bOrC.equals("C")) {
            doSomethingWithC(a);
        }
    }

    public static void doSomethingWithB(A a) {
        B b = (B) a; // possible ClassCastException
        System.out.println(b.getA());
        System.out.println(b.getB());
    }

    public static void doSomethingWithC(A a) {
        C c = (C) a; // possible ClassCastException
        System.out.println(c.getA());
        System.out.println(c.getC());
    }
}

Теперь проблема, с которой я сталкиваюсь, небезопасна. Dynami c Приведение типов, которое может столкнуться с проблемами приведения классов. Одним из возможных решений было бы создание отдельных объектов данных и установка общих полей (которых слишком много для моего реального случая) для обоих объектов отдельно в обоих классах B и C, которые затем выглядели бы следующим образом:

public class TesterClass
{
    static String bOrC = "C"; // input from some decision
    public static void main(String[] args)
    {
        if (bOrC.equals("B")) {
            B b = new B();
            b.setA(10); // duplication
            b.setB(11);
            doSomethingWithB(b);
        } else {
            C c = new C();
            c.setA(10); // duplication
            c.setC(12);
            doSomethingWithC(c);
        }
    }

    public static void doSomethingWithB(B b) {
        System.out.println(b.getA());
        System.out.println(b.getB());
    }

    public static void doSomethingWithC(C c) {
        System.out.println(c.getA());
        System.out.println(c.getC());
    }
}

Я ищу способ избежать приведения типа динамического c, но в то же время избегать дублирования общих переменных. Кто-нибудь может предложить решение?

1 Ответ

1 голос
/ 14 апреля 2020

Абстракция - это одно решение для поведения, которое вы объясняете. Создание абстрактного метода doSomething (...) в классе A и его реализация в дочернем классе B и C соответственно. Для этого вам не нужно иметь метод stati c, и обработка будет выполняться на основе самого объекта B или C.

    @Data
    class A
    {
        private int a;
        public abstract void doSomething();

    }

    @Data
    class B extends A
    {
        private int b;
        public void doSomething(){
/*.... do something here
* here you can also access parent public methods and properties.
* as you have already annotated with @Data you will have access to getA() method, * hence you can also use parent properties.
*/
        }
    }

    @Data
    class C extends A
    {
        private int c;
        public void doSomething(){
        /*.... do something here
        * here you can also access parent public methods and properties.
        * as you have already annotated with @Data you will have access to 
        * getA()         method, * hence you can also use parent properties.
        */

    }

Теперь вы можете использовать его, как показано ниже

   public static void main(Strings[] args){
       A a;
       B b = new B();
       b.setB(10);
       b.doSomething();

       C c = new C();
       c.setC(30);
       c.doSomething();
   }
...