Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8953011
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 15, 20262026-06-15T14:00:07+00:00 2026-06-15T14:00:07+00:00

Normally when I want to create a class constructor that accepts different types of

  • 0

Normally when I want to create a class constructor that accepts different types of parameters, I’ll use a kludgy overloading principle of not defining any args in the constructor definition:
e.g. for an ECEF coordinate class constructor, I want it to accept either $x, $y and $z arguments, or to accept a single array argument containg x, y and z values, or to accept a single LatLong object I’d create a constructor looking something like:

function __construct()
    {
        //  Identify if any arguments have been passed to the constructor
        if (func_num_args() > 0) {
            $args = func_get_args();
            //  Identify the overload constructor required, based on the datatype of the first argument
            $argType = gettype($args[0]);
            switch($argType) {
                case 'array' :
                     //  Array of Cartesian co-ordinate values
                     $overloadConstructor = 'setCoordinatesFromArray';
                     break;
                case 'object' :
                     //  A LatLong object that needs converting to Cartesian co-ordinate values
                     $overloadConstructor = 'setCoordinatesFromLatLong';
                     break;
                default :
                     //  Individual Cartesian co-ordinate values
                     $overloadConstructor = 'setCoordinatesFromXYZ';
                     break;
            }
            //  Call the appropriate overload constructor
            call_user_func_array(array($this,$overloadConstructor),$args);
        }
    }   //  function __construct()

I’m looking at an alternative: to provide a straight constructor with $x, $y and $z as defined arguments, and to provide static methods of createECEFfromArray() and createECEFfromLatLong() that handle all the necessary extraction of x, y and z; then create a new ECEF object using the standard constructor, and return that

Which option is cleaner from an OO purists perspective?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-15T14:00:09+00:00Added an answer on June 15, 2026 at 2:00 pm

    I’ve been thinking of the suggestions offered here and by others to clean up the overloading of the object constructor. The method I’ve decided upon is, I think, OO elegant, simple to implement and intuitive to use.

    As a solution, I decided to implement a common interface for the constructor arguments:
    I began by creating an interface.

    interface Geodetic_XyzFormat
    {
        public function getX();
        public function getY();
        public function getZ();
    }
    

    I added an abstract to implement the getters defined in the interface, together with setters and a few other methods that would be common across several child classes.

    abstract class Geodetic_ECEF_Coordinates implements Geodetic_XyzFormat
    {
        protected $_xCoordinate;
        protected $_yCoordinate;
        protected $_zCoordinate;
    
        protected function setX($xCoordinate)
        {
            $this->_xCoordinate = $xCoordinate;
        }
    
        public function getX()
        {
            return $this->_xCoordinate;
        }
    
        protected function setY($yCoordinate)
        {
            $this->_yCoordinate = $yCoordinate;
        }
    
        public function getY()
        {
            return $this->_yCoordinate;
        }
    
        protected function setZ($zCoordinate)
        {
            $this->_zCoordinate = $zCoordinate;
        }
    
        public function getZ()
        {
            return $this->_zCoordinate;
        }
    
        protected function setCoordinates($xDistance,
                                          $yDistance,
                                          $zDistance,
                                          $uom)
        {
            $this->setX(
                ($xDistance instanceof Geodetic_Distance) ? $xDistance : new Geodetic_Distance($xDistance, $uom)
            );
    
            $this->setY(
                ($yDistance instanceof Geodetic_Distance) ? $yDistance : new Geodetic_Distance($yDistance, $uom)
            );
    
            $this->setZ(
                ($zDistance instanceof Geodetic_Distance) ? $zDistance : new Geodetic_Distance($zDistance, $uom)
            );
        }
    
    }
    

    For my main class constructor, I type hinted for it to accept classes that extended the interface definition:

    class Geodetic_ECEF_TestClass
    {
        protected $_xCoordinate;
        protected $_yCoordinate;
        protected $_zCoordinate;
    
        public function __construct(Geodetic_XyzFormat $xyzCoordinates = NULL)
        {
            if (!is_null($xyzCoordinates)) {
                $this->_xCoordinate = $xyzCoordinates->getX();
                $this->_yCoordinate = $xyzCoordinates->getY();
                $this->_zCoordinate = $xyzCoordinates->getZ();
                return;
            }
    
            //    Defaults
              $this->_xCoordinate = new Geodetic_Distance();
               $this->_yCoordinate = new Geodetic_Distance();
               $this->_zCoordinate = new Geodetic_Distance();
        }
    }
    

    Finally, I created a couple of classes extending my abstract that would each handle the different options for the constructor arguments; in this case, an array of values, and individual values… I’ll write the LatLong variant later, but it will use the same basic principles and extend Geodetic_ECEF_Coordinates in the same way.

    class Geodetic_ECEF_CoordinateArray extends Geodetic_ECEF_Coordinates
    {
        public function __construct(array $coordinates = NULL, $uom = Geodetic_Distance::METRES)
        {
            if (is_null($coordinates))
                throw new Geodetic_Exception('An array of vector coordinates must be passed');
            if (count($coordinates) == 3) {
                list ($xDistance, $yDistance, $zDistance) = array_values($coordinates);
            } else {
                throw new Geodetic_Exception('Invalid number of vectors in array');
            }
    
            $this->setCoordinates($xDistance, $yDistance, $zDistance, $uom);
        }
    
    }
    
    
    class Geodetic_ECEF_CoordinateValues extends Geodetic_ECEF_Coordinates
    {
        public function __construct($xDistance = NULL,
                                    $yDistance = NULL,
                                    $zDistance = NULL,
                                    $uom = Geodetic_Distance::METRES)
        {
            $this->setCoordinates($xDistance, $yDistance, $zDistance, $uom);
        }
    
    }
    

    So now, when I instantiate an ECEF object, I pass it the appropriate Geodetic_XyzFormat object:

    //    Nothing passed to constructor
    $dummyECEF1 = new Geodetic_ECEF_TestClass();
    var_dump($dummyECEF1);
    
    //    Array of values passed to constructor
    $dummyECEF2 = new Geodetic_ECEF_TestClass(
        new Geodetic_ECEF_CoordinateArray(
            array(1.2, 3.4, 5.6)
        )
    );
    var_dump($dummyECEF2);
    
    //    Individual values passed to constructor
    $dummyECEF3 = new Geodetic_ECEF_TestClass(
        new Geodetic_ECEF_CoordinateValues(7.8, 9.1, 2.3)
    );
    var_dump($dummyECEF3);
    
    //    Individual values passed to constructor (including a NULL, which should be treated as a 0)
    $dummyECEF4 = new Geodetic_ECEF_TestClass(
        new Geodetic_ECEF_CoordinateValues(4.5, NULL, 6.7)
    );
    var_dump($dummyECEF4);
    
    $xDistance = new Geodetic_Distance(11.11, Geodetic_Distance::MILES);
    $yDistance = new Geodetic_Distance(22.22, Geodetic_Distance::MILES);
    $zDistance = new Geodetic_Distance(33.33, Geodetic_Distance::MILES);
    //    Array of distances passed to constructor
    $dummyECEF5 = new Geodetic_ECEF_TestClass(
        new Geodetic_ECEF_CoordinateArray(
            array($xDistance, $yDistance, $zDistance)
        )
    );
    var_dump($dummyECEF5);
    
    $xDistance = new Geodetic_Distance(44.44, Geodetic_Distance::MILES);
    $yDistance = new Geodetic_Distance(55.55, Geodetic_Distance::MILES);
    $zDistance = new Geodetic_Distance(66.66, Geodetic_Distance::MILES);
    //    Individual distances passed to constructor
    $dummyECEF6 = new Geodetic_ECEF_TestClass(
        new Geodetic_ECEF_CoordinateValues($xDistance, $yDistance, $zDistance)
    );
    var_dump($dummyECEF6);
    
    $xDistance = new Geodetic_Distance(11.11, Geodetic_Distance::MILES);
    $yDistance = new Geodetic_Distance(22.22, Geodetic_Distance::KILOMETRES);
    $zDistance = new Geodetic_Distance(33.33, Geodetic_Distance::MILES);
    //    Array of mixed values and distances passed to constructor
    $dummyECEF7 = new Geodetic_ECEF_TestClass(
        new Geodetic_ECEF_CoordinateArray(
            array(11, $yDistance, 33), 
            Geodetic_Distance::MILES
        )
    );
    var_dump($dummyECEF7);
    
    $xDistance = new Geodetic_Distance(44.44, Geodetic_Distance::MILES);
    $yDistance = new Geodetic_Distance(55.55, Geodetic_Distance::KILOMETRES);
    $zDistance = new Geodetic_Distance(66.66, Geodetic_Distance::INCHES);
    //    Individual mixture of distances and values passed to constructor
    $dummyECEF8 = new Geodetic_ECEF_TestClass(
        new Geodetic_ECEF_CoordinateValues($xDistance, 55, $zDistance, Geodetic_Distance::NAUTICAL_MILES)
    );
    var_dump($dummyECEF8);
    

    It doesn’t require all the kludgy tests for different argument types (whether in a factory, or in my main class), nor the use of statics (so it should be pretty easy writing unit tests for it)

    Thanks for everyone who offered suggestions and gave me food for thought

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Normally, if I want to start a new activity I can use StartActivity(typeof(foo)); This
I want to write a CMakeLists.txt so that I can run my tests normally
I want to detect when my touchpad is clicked! I normally use a usb
Normally if I had Class 1 and I wanted to use it elsewhere, I
Situation. XMLProxy Class is singleton. XMLRequest Class too. Normally, when I want to request
i want to create a polymorphic Queue association. I have two different queues in
Using Python I want to create a property in a class, but having the
I create a class that allows me to open a single instance of my
I want to create a multidimensional json object based on a c# class. I
I'm using Visual Studio 2010. I want to create a simple class which inherits

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.