7

I'm used to make pretty much all of my class variables private and create "wrapper" functions that get / set them:

class Something{
  private $var;

  function getVar(){
    $return $this->var;
  }

}

$smth = new Something();
echo $smth->getVar();

I see that a lot of people do this, so I ended up doing the same :)

Is there any advantage using them this way versus:

class Something{
  public $var;
}
$smth = new Something();
echp $smth->var;

?

I know that private means that you can't access them directly outside the class, but for me it doesn't seem very important if the variable is accessible from anywhere...

So is there any other hidden advantage that I missing with private variables?

Alex
  • 66,732
  • 177
  • 439
  • 641
  • You can find your answer in a question I asked a few months ago when I was just learning about classes: http://stackoverflow.com/questions/5034951/how-should-i-write-classes-c – Lockhead Jun 05 '11 at 13:02

5 Answers5

4

It's called encapsulation and it's a very good thing. Encapsulation insulates your class from other classes mucking about with it's internals, they only get the access that you allow through your methods. It also protects them from changes that you may make to the class internals. Without encapsulation if you make a change to a variable's name or usage, that change propagates to all other classes that use the variable. If you force them to go through a method, there's at least a chance that you'll be able to handle the change in the method and protect the other classes from the change.

tvanfosson
  • 524,688
  • 99
  • 697
  • 795
3

Access modifiers don't make a whole lot of sense in scripting languages. Many actual object-oriented languages like Python or Javascript don't have them.

And the prevalence of naive getter/setter methods is simply due to PHP not providing an explicit construct for that. http://berryllium.nl/2011/02/getters-and-setters-evil-or-necessary-evil/

mario
  • 144,265
  • 20
  • 237
  • 291
  • 2
    They make perfect sense when they are enforced, same as they do in other languages. – Orbling Jun 05 '11 at 13:04
  • Their overuse quite often indicates a misunderstanding of core OOP concepts, like messaging and the purpose of encapsulation. – mario Jun 05 '11 at 13:12
  • @mario: I disagree, all instantiated variables should have an access modifier on them, to note their scope if nothing else. – Orbling Jun 05 '11 at 13:16
  • That's just an opinion. I don't see much practical value in that. And I'm only ever declaring properties as protected or private *if and only if* there is an actual reason. Habitual syntax construct usage doesn't aid code quality. – mario Jun 05 '11 at 13:26
  • @mario: Everything that has choice implies an opinion. If you do not list the access modifier, a default is assumed by the compiler, it is unclean to rely on a compiler default rather than stating something explicitly, for all of the second it takes to type something specific. – Orbling Jun 05 '11 at 13:35
  • @Orbling: There is no compiler. Otherwise we would not have this discussion (makes a damn significant difference if access modifiers are evaluated and violations are detected at the compiling stage or if they blow up at runtime). -- In PHP the `public` modifier is implicit. And that's it. It's an redundant decoration, not necessary, not beneficial. It's syntactic salt, used for appearance coding only (looks more "professional" / "PHP5ish" / "clean" / whatever). – mario Jun 05 '11 at 13:41
  • @mario: PHP code may be interpreted, but it is still parsed and partially compiled, whether the language is interpreted or compiled to machine code / bytecode has no bearing on the validity of the semantics. Coding standards are largely about appearance, to reduce assumptions and enable others to be able to read your code. In PHP5 access modifiers do mean something and yes it is more professional, because it leaves no doubt, an omission maybe accidental. – Orbling Jun 05 '11 at 15:01
  • Did you understand the part about compile time and run time access modifier interpretation? What people see as access modifiers in PHP is quite distinct from those in Java. Yet people keep confounding their presence with quality or professionalism. But uneeded cruft generally isn't. And `var` and `public` are aliases. – mario Jun 05 '11 at 15:22
  • @mario: Yes, I understood it just fine thanks. Yes, it would be better for it to be a static check, rather than dynamic, but such errors would still be picked up on first run. `var` and `public` are aliases due to the usual PHP problem of backwards compatibility, as is the omission of an access modifier. Just because these defaults and compatibility allowances exist, does not mean they should be promoted. Anyhow, as you stated earlier, it is a matter of opinion here, so this is not the venue for it. – Orbling Jun 05 '11 at 16:22
3

It differs from case to case if you want to use private variables with public getters and setters or if you just want to declare a variable as public directly.

The reason it might be good to use "getters" and "setters" is if you want to have control over when someone accessess the data.

As an example, lets say you got this:

public setBirthday($date)

Then you can make sure that the date passed in to that setter is a valid birthdate.

But you can't if you just declare the variable as public like this

public $birthday;

Based on comments.

Also, if you decide change the internal storage mechanism from a string containing the date to the number of seconds since 1/1/1970, you can still present the date externally in the same way if you use encapsulation, but not if you expose the variables directly. Every piece of code that touched the internal variable directly would now be broken.

This means that if the internal storage mechanism would change to numbers of seconds from 1/1/1970 then you don't have to change the 'External API'. The reason is because you have full control over it:

public getBirthday() {
  // you can still return a string formatted date, even though your 
  // private variable contains number of seconds from 1/1/1970
}
Fredrik
  • 2,016
  • 3
  • 15
  • 26
  • Also, if you decide change the internal storage mechanism from a string containing the date to the number of seconds since 1/1/1970, you can still present the date externally in the same way if you use encapsulation, but not if you expose the variables directly. Every piece of code that touched the internal variable directly would now be broken. – tvanfosson Jun 05 '11 at 13:08
2

It is to demark variables that are internal to the implementation of the class, from variables that are intended for external change. There are also protected variables, which are for internal use, and use by extensions to the class.

We make the variables private so that only the code within the class can modify the variables, protecting interference from outside, guaranteeing control and expected behaviour of the variable.

Orbling
  • 20,413
  • 3
  • 53
  • 64
2

The purpose of encapsulation is to hide the internals of an object from other objects. The idea is that the external footprint of the object constitutes it's defined type, think of it like a contract with other objects. Internally, it may have to jump through some hoops to provide the outward-facing functionality, but that's of no concern to other objects. They shouldn't be able to mess with it.

For example, let's say you have a class which provides calculations for sales tax. Some kind of utility service object, basically. It has a handful of methods which provide the necessary functionality.

Internally, that class is hitting a database to get some values (tax for a given jurisdiction, for example) in order to perform the calculations. It may be maintaining a database connection and other database-related things internally, but other classes don't need to know about that. Other classes are concerned only with the outward facing contract of functionality.

Suppose sometime later the database needs to be replaced with an external web service. (The company is going with a service for calculating sales tax rather than maintain it internally.). Because the class is encapsulated, you can change its internal implementation to use the service instead of the database very easily. The class just needs to continue to provide the same outward facing functionality.

If other classes were mucking around with the internals of the class, then re-implementing it would risk breaking others parts of the system.

David
  • 208,112
  • 36
  • 198
  • 279