0
votes
  1. Is there a way to get rid of the getCopy() method in the derived class HelloAndGoodbye, given that it looks the same as the getCopy() in the base class Hello?

  2. And what is more, what is there an efficient way to achieve this?

(the only difference between the two functions is that in the baseclass 'static' refers to 'Hello' and in the derived class 'static' refers to 'HelloAndGoodbye; as for the variables contained therein they can be easily renamed so that they are the same in both functions).

<?php

class Hello {

  private $hello;

  public function createStub() {

    return new static(null);

  }

  public function __construct($hello) {

    $this->setHello($hello);

  }

  public function getCopy() {

    $helloCopy = static::createStub();

    $this->doCopy($helloCopy);

    return $helloCopy;

  }

  public function doCopy($helloCopy) {

    $helloCopy->setHello($this->hello);

  }

  public function setHello($hello) {

    $this->hello = $hello;

  }

  public function getHello($hello) {

    return $this->hello;

  }

  public function __toString() {

    return $this->hello . "\n";

  }

}

class HelloAndGoodbye extends Hello {

  private $goodbye;

  public function createStub() {

    return new static(null, null);

  }

  public function __construct($hello, $goodbye) {

    parent::__construct($hello);

    $this->setGoodbye($goodbye);

  }

  public function getCopy() {

    $helloAndGoodbyeCopy = static::createStub();

    $this->doCopy($helloAndGoodbyeCopy);

    return $helloAndGoodbyeCopy;

  }

  public function doCopy($helloAndGoodbyeCopy) {

    parent::doCopy($helloAndGoodbyeCopy);

    $helloAndGoodbyeCopy->setGoodbye($this->goodbye);

  }

  public function setGoodbye($goodbye) {

    $this->goodbye = $goodbye;

  }

  public function getGoodbye($goodbye) {

    return $this->goodbye;

  }

  public function __toString() {

    return parent::__toString() . $this->goodbye . "\n";

  }

}

function test() {

  $hello = new Hello("Hello John");

  $helloAndGoodbye = new HelloAndGoodbye("Hello Jane", "Goodbye Jane");

  echo $hello;

  echo $helloAndGoodbye;

}

test();

OUTPUT:

Hello John
Hello Jane
Goodbye Jane
1
Is there any good reason for getCopy() and doCopy() to exist? A simple $copy = clone $hello; does the same as $copy = $hello->getCopy(); without needing the two functions mentioned above. And if you really need some special initialization of the copy you can always implement __clone(). - axiac
Well, the reason I did not use clone and implement __clone() is that in the real case code scenario I am considering, some objects must be deep copied and some shallow copied,so I decided to write my own functions. doCopy() is separated from getCopy() so that it can be called from the subclass: this way adding a property to the parent class will mean I only have to add some code to doCopy() in the parent class and not reduplicate that code in the subclass. - John Sonderson
Consider the case where $hello and $goodbye will be objects rather than primitive string data types. - John Sonderson
Implementing __clone() in class Hello, its subclasses and the classes used by them should be enough. If you have cases when an object of a class must be deep copied or shallow copied depending on the context then you probably crammed too much functionality in that class. - axiac

1 Answers

0
votes

I found a solution to the problem at hand by means of using the __CLASS__ PHP constant which correspond to the name of the class within which it appears. This allowed me to get rid of the pseudo-duplicate getCopy() method in the derived class, while still allowing getCopy() to work fine on both:

<?php

class Hello {

  private $hello;

  public function createStub() {

    return new static(null);

  }

  public function __construct($hello) {

    $this->setHello($hello);

  }

  public function getCopy() {

    $class = __CLASS;

    $instanceCopy = $class::createStub();

    $this->doCopy($instanceCopy);

    return $instanceCopy;

  }

  public function doCopy($helloCopy) {

    $helloCopy->setHello($this->hello);

  }

  public function setHello($hello) {

    $this->hello = $hello;

  }

  public function getHello($hello) {

    return $this->hello;

  }

  public function __toString() {

    return $this->hello . "\n";

  }

}

class HelloAndGoodbye extends Hello {

  private $goodbye;

  public function createStub() {

    return new static(null, null);

  }

  public function __construct($hello, $goodbye) {

    parent::__construct($hello);

    $this->setGoodbye($goodbye);

  }

  public function doCopy($helloAndGoodbyeCopy) {

    parent::doCopy($helloAndGoodbyeCopy);

    $helloAndGoodbyeCopy->setGoodbye($this->goodbye);

  }

  public function setGoodbye($goodbye) {

    $this->goodbye = $goodbye;

  }

  public function getGoodbye($goodbye) {

    return $this->goodbye;

  }

  public function __toString() {

    return parent::__toString() . $this->goodbye . "\n";

  }

}

function test() {

  $hello = new Hello("Hello John");

  $helloAndGoodbye = new HelloAndGoodbye("Hello Jane", "Goodbye Jane");

  echo $hello;

  echo $helloAndGoodbye;

}

test();

OUTPUT:

Hello John
Hello Jane
Goodbye Jane