...

View Full Version : Resolved Public, protected, and private?



RonnyNishimoto
07-20-2012, 05:07 AM
Why would someone make something protected or private? There doesn't seem to be much use for them, it's basically limiting public? Why would you want to limit public? Is it just for efficiency/matches better.

From researching:
- public scope to make that variable/function available from anywhere, other classes and instances of the object.
- private scope when you what your variable/function to be visible in its own class only.
- protected scope when you want to make your variable/function visible in all classes that extend current class.

Thanks!

Dormilich
07-20-2012, 06:59 AM
because public allows uncontrolled access. in case of public properties, it is even worse as you can change the property without a guarantee of data integrity.

ex.1 say you have a public property named age of a Person class. you can set this property to anything you like: negative numbers, strings, objects, whatever. but then a calculation based on this age is bound to fail. if you had a protected/private property, you need to use a method to modify the age value, which you can then validate before saving.

ex.2 say you have a public method that closes the DB connection. normally you close the connection when you’re done with the DB work. with this method public, you could close the connection at an arbitrary time making the following DB code fail.

MarkR
07-20-2012, 11:51 AM
Imagine this:




class Safe {


private $id;


function __construct(){

//set id here
}

function get_id(){

return $this->id;
}


}

class Vuln{

public $id;

function __construct(){

//set id here
}

}



//Consider the following:

$Safe = new Safe();
$Vuln = new Vuln();

if( $Safe->get_id() = $comparison ){


//run important stuff
}

if( $Vuln->id = $comparison ){


//run important stuff
}




It's a simple error most have made, using the setter operator instead of the comparison inside an if statement. It could get pretty nasty if you change the value of a variable accidentally you are relying on to hold a certain value.

It all depends though, with this style of programming comes with a hit to execution time so it's best to enforce scope only on important functions and variables. Look here:

http://stackoverflow.com/questions/6215398/calling-the-variable-property-directly-vs-getter-setters-oop-design

Fou-Lu
07-20-2012, 02:11 PM
This thread made me lol.
Its all about control. Datatype strong languages are already bad enough:


public class Circle
{
public int iRadius;

public double getArea()
{
return Math.PI * this.iRadius;
}
}

//. . .
Circle c = new Circle();
c.iRadius = -4;
c.getArea(); // -12.5ish

At least there you can't do c.iRadius = "a string", but -12 is still an invalid area.

Now the same in PHP, with its datatype weakness you don't even get the benefit of a rejection on setting $c->iRadius = "a string". This is why you need to set up accessors and mutators so you can throw exceptions on invalid input.

So needless to say, your properties should always be either private or protected depending on if you want child classes to manipulate them directly. Use mutators and accessors for them otherwise.
Same goes for the methods as well. If they are never required for external control, then make them private or protected (Dormlich has a good description of one).

RonnyNishimoto
07-20-2012, 08:14 PM
Okay ex2 from Dromilich and Fou's area are bad values.

But how does making something public/private/protected change that? Are you saying that IF someone set c.iRadius to -4, it could return a bad value. But how would public/private/protected make it not return a bad value.

You are saying that if it were private/protected, c.iRadius could only be placed inside the function. But that would still return a bad value?

Keleth
07-20-2012, 08:17 PM
Well, the point is if its public, you/the user can change it any time, with no sanity added.

If its private/protected, it can only be changed via a function, in which you can place checks for sanity.

So if you made iRadius -4 public, you could do that, and a later function would fail. If instead it was private and in the function changeRadius, you could check internally that its a number > 0. If the variable was supposed to be a string made only of alphanumerics, you could remove non-alphanums, etc. Basically, by using accessors and mutators, you control what the variable is, rather then relying on the rest of the code to set it.

RonnyNishimoto
07-20-2012, 08:26 PM
Okay accessors/mutators is the same as getters/setters.

I'm understanding now. The main question I'm having is in Fou's example, if he had validation within the function, then making it protected/private means the "-4" has to go through validation.

But he chose to stick the radius outside the function and validation. You would have to choose to make a mistake.

"Private scope when you want your variable/function to be visible in its own class only."
My main point is: if the example used private, then you wouldn't be allowed to set the variable outside the function without an obj variable. But when would you ever set it outside the function? Isn't that a human error?

Dormilich
07-20-2012, 08:46 PM
But when would you ever set it outside the function? Isn't that a human error?
that’s correct.

well, help forums wouldn’t be as present if humans weren’t producing errors in programming all the time.

RonnyNishimoto
07-20-2012, 08:53 PM
You know I still don't completely understand, but I think as I go along it will make more sense. :)

Thank you everyone! Moving on to mySQL!

Fou-Lu
07-20-2012, 10:11 PM
No error in what I have above. The problem is that there is no sanity on the iRadius in the example I provided since it is public, which is what the point of the example was.
The way to do that would be to provide it with a mutator (setter), so that it can be controlled upon population.


class Circle
{
private $iRadius;

public function getRadius()
{
return $this->iRadius;
}
public function setRadius($i)
{
if (!is_numeric($i) || $i < 0)
{
throw new InvalidArgumentException('Radius must be a number > 0');
}
$this->iRadius = $i;
}
public function getArea()
{
return pow($this->iRadius, 2) * M_PI;
}
}

$c = new Circle();
try
{
$c->setRadius(-4);
printf('The area of a circle with raidus %0.5f is %0.5f', $c->getRadius(), $c->getArea());
}
catch (InvalidArgumentException $ex)
{
print $ex->getMessage();
}

Now circle can never be in a state with an invalid radius (although the rules I specified say that 0 is a valid raidus), and therefore I can always calculate an Area.

And don't assume that one has to execute the error manually. Building generic code with OOP often results in foreign code extensions. Not to mention that if I change that -4 to $_POST['radius'] then I have no control over what is actually entered, only what happens with what was entered.


Oh I did actually have an error. That radius should have been squared in the Java code before multiplying pi. Meh, doesn't really change the point I was trying to make :P

RonnyNishimoto
07-20-2012, 11:02 PM
They makes it slightly clearer. Until I fully understand I am going to just choose random ones :D

Edit: No actually I got it now, it just clicked :)

I'm just going to use private/protected with things that could potentially cause an error to my results. And as I code more, I will learn more uses. Thanks guys!



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum