Jump to content
Sign in to follow this  
NotionCommotion

Should properties with methods be public or private?

Recommended Posts

I expect an "it depends" answer, and if so, then "should properties with methods ever be public?".  Also, please do not reply with a just yes or no, but provide the why.  Thank you

<?php

class SubObject
{
    public function doSomething() {
        echo("something\n");
    }
}

class Obj1
{
    public $subObject;
    public function __construct(SubObject $subObject) {
        $this->subObject=$subObject;
    }
}

class Obj2
{
    private $subObject;
    public function __construct(SubObject $subObject) {
        $this->subObject=$subObject;
    }
    public function doSomething() {
       $this->subObject->doSomething();
    }
}

$subObject=new SubObject();

$obj1=new Obj1($subObject);
$obj1->subObject->doSomething();

$obj2=new Obj2($subObject);
$obj2->doSomething();

 

Share this post


Link to post
Share on other sites

Isn't this basically the same question we talked about here? I do realize there's a slight difference, but unless I'm missing something that difference seems extremely small.

Share this post


Link to post
Share on other sites
15 hours ago, maxxd said:

Isn't this basically the same question we talked about here? I do realize there's a slight difference, but unless I'm missing something that difference seems extremely small.

I didn't think it was the same question since we are talking primarily about methods and also not entity classes and therefore asked it.  You appear to think so, however, and if so you feel that "sub-methods" should not be made visible.  True?

Doesn't keeping them private or protected conflict with open/closed principle?  And regardless of academia, don't you think it s a pain in the butt to mirror all the methods?

Share this post


Link to post
Share on other sites

As far as I view it, scope is scope whether it related to methods or properties. Of course, that's easy for me to say because I believe most things should be privately scoped anyway - at least initially. More on that later...

The Open/Closed principle (quoting Wikipedia here) states that "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification". Using private (and to a degree protected) methods and properties - the way I understand it, anyway - is the basic building block of the principle. By using public getters and setters, you've created an effective and reliable API that other differently typed objects and classes can use with confidence. So you've got the extension aspect covered with the public API, but by encapsulating the inner guts of the class with private scope, it's tightly closed to modification except where monitored and expected.

Personally I thinks it's better to start off with a tighter scope (private), then loosen up on methods as necessary to create your API. As ignace points out in the other thread (this post) if you find you need to give privileged information to a child object, set that information's scope to protected.

All that having been said, I am a bit more strident in my belief that properties should be private no matter what. Methods need to be public at times - properties don't. By using a setter method you can validate and control the value before you assign it to a local property, and using a getter method allows you to tailor the response. And yes, it is sometimes a pain to write pass-through methods to sub-objects, but I feel the trade-off in system security and consistency is worth the time.

Hopefully this all makes some sort of sense - I'm trying to quit smoking this week and my brain's having trouble keeping up.

Share this post


Link to post
Share on other sites

Properties are like your intestines, you don't want anyone else to touch them. Unless, perhaps for surgery (my architect mind is already modelling this, I'll spare you the details). Therefor they should always be private. If something does need access, they can use an interface you control.

In certain cases you could opt to mirror methods instead of exposing the sub-object, but it's certainly not advisable to mirror the entire interface. In this case, just create a getter. But don't ever expose a public property, you are inviting bugs. PHP does not yet have the powers other OO languages have.

 

Edited by ignace

Share this post


Link to post
Share on other sites

Thanks maxxd and ignace,  Ah, a 3rd option.  You mean something like the following, correct?

class SubObject implements SubObjectInterface
{
    public function doSomething() {
        echo("something\n");
    }
}

class Obj implements ObjInterface
{
    private $subObject;
    public function __construct(SubObject $subObject) {
        $this->subObject=$subObject;
    }
    public function getSubObject() {
       return $this->subObject;
    }
}

$subObject=new SubObject();
$obj1=new Obj($subObject);
$obj->getSubObject()->doSomething();

 

  • Like 1

Share this post


Link to post
Share on other sites
3 hours ago, ignace said:

Properties are like your intestines, you don't want anyone else to touch them. Unless, perhaps for surgery (my architect mind is already modelling this, I'll spare you the details). Therefor they should always be private.

That just made me shoot milk out my nose and I haven't had milk in years.

NotionCommotion - yes, just like that. Unless you have a reason to hide the sub-objects interface or you need to do some manipulation before or after interacting with the sub-object, in which case write the pass-through method.

Share this post


Link to post
Share on other sites

You create a class, and the class has a public data structure in it that happens to be a simple one dimensional numerically indexed array.

Things are working ok, so you start utilizing the class definition, and in your code you access the array using $foo->var..

Let's assume this is a large project and you are accessing that array all over the place.

Now you realize that the structure of the array isn't ideal for what you are doing, so you change the internal class variable to be an array of objects.

How much of your system did you break?  Answer:  everywhere you refer to $foo->var!

If however, you only utilize public methods, then it is possible to change the internal data structure without breaking the entire system.  So long as the original method continues to return the one dimensional array, it doesn't matter that you changed the internal data structure.

In OOP this concept is referred to as "data hiding" and "encapsulation".

The other option you left out of your question, is 'protected'.  In general, your data should either by private or protected in order to hide it from the outside world.  If you expect your class to be the parent/superclass for other classes that will inherit/subclass it, then you should choose protected if you will be accessing those properties in the subclass.  If not, then make them private.  Either way, you don't want to have public properties which can subvert your public API and violate Encapsulation.  

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.