Професионална програма
Loading...
VenelinGrozev avatar VenelinGrozev 130 Точки

[Technical Issue] Java OOP subtyping

Здравейте,

Имам малък проблем с разбирането на subtyping-a при Java List-вете. Става въпрос за първа задача от домашното. Пускам по-долу скелета на класовете

public class Vertex2D {
    private double x;
    private double y;
}

public class Vertex3D extends Vertex2D {
    private double z;
}

public abstract class Shape {
    protected List<? extends Vertex2D> vertices;

    public Shape() {
    }

    public Shape(List<? extends Vertex2D> vertices) {
        this.vertices = vertices;
    }
}

public class PlaneShape extends Shape {
    private Vertex2D vertex;

    public PlaneShape(Vertex2D vertex) {

        this.vertices = new ArrayList<Vertex2D>();
        this.vertices.add(vertex); // compile error
        // The method add(capture#2-of ? extends Vertex2D)
        // in the type List<capture#2-of ? extends Vertex2D>
        // is not applicable for the arguments (Vertex2D)
    }
}

Не мога да разбера защо при инициализация на конструктора на PlaneShape въпреки, че this.vertices става new ArrayList<Vertex2D>() не мога да вкарам в него променлива от тип Vertex2D.

В същото време това решение по-долу работи без проблем

public PlaneShape(Vertex2D vertex) {

        List<Vertex2D> verticesArray = new ArrayList<Vertex2D>();
        verticesArray.add(vertex);
        this.vertices = verticesArray;
    }

 

Явно, че пропускам нещо но не мога да разбера какво, затова всякаква помощ е добре дошла.

Тагове:
0
C# OOP Basics
Filkolev avatar Filkolev 4482 Точки

С такива геометрични задачи наследяванията са доста сложни като логика. В случая триизмерната точка наследява двуизмерната, което е спорно. Има две решения да изчистиш логиката, за които се сещам.

1) Да направиш абстрактен клас за точките и двуизмерните и триизмерните да го наследяват, при което Shape ще приема списък от Vertex, а вече наследниците на Shape ще конкретизират какви точно точки приемат. Аз така подходих.

2) Shape да е празен клас, т.е. да няма списък с точки, евентуално да имплементира интерфейса AreaCalculatable, понеже всички фигури могат да си смятат лицето. 

Не съм сигурен какъв е проблемът, може би "? extends Vertex2D" очаква наследник на Vertex2D, но не приема самия Vertex2D? Не съм ползвал този синтаксис.

0
VenelinGrozev avatar VenelinGrozev 130 Точки

В началото и аз направих абстрактен клас Vertex но се оказа, че няма нужда от него, понеже не знам какво да държа вътре. Реално в основният клас Vertex имам координати х и у, защото това е минимума с който можеш да опишеш една точка. После имаш нужда от още един клас за 3D точките, който да има и още една координата z. Какво държиш в базовият клас Vertex?

Това, че Shape класа ще имплементира AreaCalculatable не помага много. Имам предвид, че - да, трябва да имплементира AreaCalculatable но това не помага да си реша проблема.

List<? extends Vertex2D> значи - направи List в който можеш да слагаш само обекти от тип Vertex2D или наследници на този тип.

Също така имаш и израза List<? super Vertex2D>, който значи - направи List в който можеш да слагаш обекти от тип Vertex2D или негови родители. В случаят основният родител е Object.

0
Filkolev avatar Filkolev 4482 Точки

Нищо нямам във Vertex, направил съм го само като абстракция, за да мога да го ползвам в Shape. Не съм привърженик на празни класове, но е някакво решение.

0