0

Abstract class hide the implementation and group of similar type data.

Group of data is understandable but implementation hiding is not.

According to the following code:

abstract class area
{
    protected $a;
    protected $b;

    abstract public function CalculateArea($ax, $ay); 
}

class rectangle extends area
{
    public function CalculateArea($ax, $ay)
    {
       $this->a = $ax; 
       $this->b = $ay; 

       return $this->a * $this->b;
    }
}

class ellipse extends area
{
    private $c = 3.1416;
    public function CalculateArea($ax, $ay)
    {
       $this->a = $ax; 
       $this->b = $ay; 

       return $this->a * $this->b * $this->c;
    }
}

$RectangleArea = new rectangle();
echo $RectangleArea->CalculateArea(2, 3);

echo"<br>\n";

$EllipseArea = new ellipse();
echo $EllipseArea->CalculateArea(2, 3);

Here a,b properties in abstract class area that is used to next inherited class rectangle and ellipse. Through this it is understandable that grouping of data satisfied but how the implementation hiding is satisfied? Can anyone clarify it?

Thanks in advance.

hakre
  • 193,403
  • 52
  • 435
  • 836
Chunk
  • 37
  • 7

2 Answers2

0

In your abstract class $a and $b are protected.

abstract class area{
    protected $a;
    protected $b;

    abstract public function CalculateArea($ax,$ay); 
}

This is how visibility works:

  • public to make property/method available from anywhere, other classes and instances of the object.

  • private when you want your property/method to be visible in its own class only.

  • protected when you want to make your property/method visible in all classes that extend the current class including the parent class.

If you don't use any visibility modifier, the property/method will be public.

see this for reference https://stackoverflow.com/a/4361582/9354303

Kulshreshth K
  • 1,096
  • 1
  • 12
  • 28
0

What's presented is an interface, because the actual logic is pushed down into the implementing class, which doesn't, in fact, create a hidden implementation.

Here's a modified example demonstrating something closer to what you're describing, because you access through area() but the implementation is private to the abstract class.

trait CalculatesArea
{
    private $pi = 3.1416;
    
    private function rectangularArea(): float
    {
       return $this->a * $this->b;
    }
    
    private function ellipticArea(): float
    {
       return $this->a * $this->b * $this->pi;
    }
}

abstract class Shape
{
    use CalculatesArea;
    
    public function __construct(protected float $a, protected float $b) {}

    public function area(): ?float
    {
        if ($this instanceof Rectangle) {
            return $this->rectangularArea();
        }
        
        if ($this instanceof Ellipse) {
            return $this->ellipticArea();
        }
        
        return null;
    }
}

At this point, we have an abstract class that utilizes a trait and determines, based on checking it's final implementation, which area method to use.

Now we just extend it and each uses a common ->area() invocation to call into the abstract class:

class Rectangle extends Shape {}

class Ellipse extends Shape {}

var_dump(
    (new Rectangle(3, 4))->area(),
    (new Ellipse(1.3, 3.8))->area(),
);

https://3v4l.org/l3RTl#v8.2.0

Because the trait has the calculate methods as private, they are "hidden" (private method) from the implementing class (protected method), as well as any external code (public method).

Jared Farrish
  • 48,585
  • 17
  • 95
  • 104
  • Interesting. It was my understanding so far, that for *implementation hiding* it would be enough to have the public interface and don't change it while the implementation can change. – hakre Dec 14 '22 at 12:55
  • @hakre If it's wrong, I can remove it. I trust you. (Been a while!) – Jared Farrish Dec 14 '22 at 12:56
  • No, please don't. I just read your answer and found it well explained, it was more the interesting moment I had that I wanted to share in the comment. Cheers! – hakre Dec 14 '22 at 13:00
  • @hakre 30 minutes ago I went "Implementation hiding, what's that?!?" This seemed like what it was to me, at least. – Jared Farrish Dec 14 '22 at 13:03
  • I'd say so as well as it does hide the implementation. And good food for thought. I'm chewing on the part with the "pushing down", I'm always wondering where down or up is. ^^. The example could spare the two ifs by making both child classes use the trait and the private method directly. This is perhaps how I'd done it. I also like the idea to have some minuscule strategy "pattern" built-in. – hakre Dec 14 '22 at 13:17
  • @hakre Be interested to see that. IMO there's only so many ways to calculate area, so having a decider the public method demonstrates the hiding concept cleanly. Here I mean "down" as in "details in the implementation", with interfaces being high-level abstractions, hence making the low-level details pushed "down" into the concrete implementation. – Jared Farrish Dec 14 '22 at 13:26
  • https://3v4l.org/hZt7d#v8.2.0 - also now with constant in trait, as implemented in PHP 8.2 - https://wiki.php.net/rfc/constants_in_traits ;) -- in the example the event is still pushed down to the implementation, it is just that the binding is within the child classes, that now can fully decide each of their how. removes the if and null from the return type, considering that every shape has an area of type float, never null. – hakre Dec 14 '22 at 13:49
  • @hakre I like it. Nice constant name `:)` – Jared Farrish Dec 14 '22 at 13:54