So, I have defined some data structures as php classes with properties only (similar syntax to C/C++ struct). To be type strict in an easy way and have properties common for all the structures in one place - I figured out to define first basic structure as abstract class - it should never be instantiated, and all the "really used" structures will be extending it. Working example:
// Parent struct def: Common data for all the shapes, not meant to be instantiated
abstract class Shape {
public int $posX, $posY;
public string $color;
}
// Real structure def: I would like to use this one in code a real structure
class Rectangle extends Shape {
public int $width, $height;
}
Then, I tried to define classes for working with these structures. Concept was very similar: basic abstract class with features common for all the structures, and one child class extending it for each structure. Continuing previous working example:
abstract class ShapeRenderer {
public Shape $shapeData;
public function SetShapeData(Shape $shapeData) {
$this->shapeData = $shapeData;
}
}
class RectangleRenderer extends ShapeRenderer {
public Rectangle $shapeData; // fatal error line
public function SetShapeData(Rectangle $shapeData) { // warning here
$this->shapeData = $shapeData;
}
}
// init these variables for some testing after
$rect = new Rectangle();
$rect->width = 10;
$render = new RectangleRenderer();
$render->SetShapeData($rect);
Sadly, I cannot override type of inherited property $shapeData from abstract Shape to real one which is extending it - Rectangle (line with comment "fatal error line") gives:
Fatal error: Type of RectangleRenderer::$shapeData must be Shape (as in class ShapeRenderer)
So I commented that line. Still same error was happing when I did override param type from Shape to more strict Rectangle in ShapeRenderer method SetShapeData. Changing parent method to abstract one without a body in ShapeRenderer resulted in exchanging fatal error for a warning:
Warning: Declaration of RectangleRenderer::SetShapeData(Rectangle $shapeData) should be compatible with ShapeRenderer::SetShapeData(Shape $shapeData)
The code seems to be working, I can access $render->shapeData->width dirrectly just fine, but when i try to var_dump whole $render->shapeData it says that it's of type Shape and doesn't have property width. So it's clearly not the good solution
Is there any way to handle it other than:
declare property $shapeData without specyfing its type, only once - in common abstract class ShapeRenderer remove declaration of $shapeData in common abstract class ShapeRenderer (+ all code accessing it there), and declare it only in every child class (using any type) ? Both ways doesn't sound right to me