The SitePoint Forums have moved.

You can now find them here.
This forum is now closed to new posts, but you can browse existing content.
You can find out more information about the move and how to open a new account (if necessary) here.
If you get stuck you can get support by emailing forums@sitepoint.com

If this is your first visit, be sure to
check out the FAQ by clicking the
link above. You may have to register
before you can post: click the register link above to proceed. To start viewing messages,
select the forum that you want to visit from the selection below.

Dudes, learn OOP. Keyword: encapsulation. Attributes should be as private as possible and methods should be as public as possible.

Did you fall asleep before getting to the Polymorphism chapter? How do you redeclare the same attributes in the subclass? You might need to do this to give an attribute in the subclass a different default value.

In OOP this is called overriding. You can declare you attributes private only if you are psychic, do not support inheritance or you are some kind of mad scientist that uses an artificial language just to make a point.

Did you fall asleep before getting to the Polymorphism chapter? How do you redeclare the same attributes in the subclass? You might need to do this to give an attribute in the subclass a different default value.

In OOP this is called overriding. You can declare you attributes private only if you are psychic, do not support inheritance or you are some kind of mad scientist that uses an artificial language just to make a point.

If you're going to give it a different default value, you should run the setter function in the constructor of the new subclass. It's not much harder than that.

Never set the default value at the same time as declaration. Do it in the constructor. Always. The object should only be considered fully instantiated once the constructor has run anyways.

Ruby has a few idiosyncrasies like that; having 0 evaluate to true (rather than false) is another. But having private available to subclasses makes more sense anyway.

Originally Posted by kyberfabrikken

I'm some times missing a friend access modifier. This would allow you to expose members, but only to a certain number of classes. That would be quite useful, if you use a lot of aggregation.

I don't know, I've always thought that over reliance on "friend" can lead to hard to maintain code.

Originally Posted by kyberfabrikken

Ruby does another thing though, which is very nifty; It makes all properties protected, and only allows you to expose methods. This is something, which is clever to enforce at the language level. In contrast, PHP makes all properties public by default.

Ruby also makes it trivial to add getters and setters, so there's no reason to make properties public anyway.

I don't know, I've always thought that over reliance on "friend" can lead to hard to maintain code.

If the alternative was public, I think it would be preferable. I'm not sure though. Right now, I just end up with a lot of public functions and a lot of protected attributes, and frankly it doesn't bother me too much. The friend accessor has another problem associated with it, in that it would tend to create concrete class dependencies (Unless a friend could be an interface).
All very theoretical -- I'm not at all suggesting, that this should be introduced into PHP at this point. That would just serve to further muddle things.

Dudes, learn OOP. Keyword: encapsulation. Attributes should be as private as possible and methods should be as public as possible.

Nonononono!

The principle is actually very easy:

1. The objects are defined by their behavior.
2. The behavior is defined by actions the objects can perform.
3. Those actions are defined with the methods that can be called by other objects.
4. Only those methods should be "public" (i.e. callable from outside).
5. Everything else (attributes or objects) should be "private" (i.e. only callable/visible/modifiable from inside).

And once again, the inheritance rights should be at least completely separate from access rights, and ideally they should be restricted in no way -- a subclass should automatically inherit everything the parent class has.

Just think of it in terms of real world objects. We never know properties of objects unless we do some action: we have to ask a person for their name, we have to look at an object to see its color etc. The same principle should apply to objects in programming.

Another issue is that people tend to think of objects in term of classes, instead in terms of instances. None of us is a Person; we are instances of a Person class, each with different attributes and details. When we interact, it's not a Person interacting with a person -- it's Berislav interacting with Athox, for instance.

If you're going to give it a different default value, you should run the setter function in the constructor of the new subclass. It's not much harder than that

What you are doing is wrong. Your subclasses are setting values inside the constructor, and that's an odd way of overriding values and dealing with polymorphism.

What you are doing is hiding the class instantiation behaviour inside a method. So, by looking at your API or documentation no one will ever know the values that you are overriding. This is not about getters and setters, is about overriding attributes in a transparent way.

1. The objects are defined by their behavior.
2. The behavior is defined by actions the objects can perform.
3. Those actions are defined with the methods that can be called by other objects.
4. Only those methods should be "public" (i.e. callable from outside).
5. Everything else (attributes or objects) should be "private" (i.e. only callable/visible/modifiable from inside).

And once again, the inheritance rights should be at least completely separate from access rights, and ideally they should be restricted in no way -- a subclass should automatically inherit everything the parent class has.

Just think of it in terms of real world objects. We never know properties of objects unless we do some action: we have to ask a person for their name, we have to look at an object to see its color etc. The same principle should apply to objects in programming.

Another issue is that people tend to think of objects in term of classes, instead in terms of instances. None of us is a Person; we are instances of a Person class, each with different attributes and details. When we interact, it's not a Person interacting with a person -- it's Berislav interacting with Athox, for instance.

What you are doing is wrong. Your subclasses are setting values inside the constructor, and that's an odd way of overriding values and dealing with polymorphism.

What you are doing is hiding the class instantiation behaviour inside a method. So, by looking at your API or documentation no one will ever know the values that you are overriding. This is not about getters and setters, is about overriding attributes in a transparent way.

If you've ever programmed in C++, you'll know that initializing a class attribute at the same time as declaration is wrong.

The attribute values are what makes the object unique. You should avoid "default" values. If you can't set all the "defaultized" attributes at the constructor, then there's a doubtful need of the attribute.

In a subclass constructor, you should always call the parent constructor as well, like in the following code, unless the functionality of the constructor is to OVERRIDE the parent constructor COMPLETELY.

PHP Code:

class A {
protected $var; // should be private, but protected for this example
protected $var2; // same

public function __construct() {
$this->var = true; // should go through a setter, but for example
$this->var2 = false; // same
}
}

class B extends A {
public function __construct() {
// you don't know what other things the parent construct
// might do, and all you want to do is change the initial value of the
// $var.
parent::__construct();
$this->var = false;
}
}

Mostly a hint about C/C++ having a very strong separation between compile time and run time. In PHP, this border is blurred.

Amazing how people are getting stuck on the things that don't matter in this discussion. I'll try that too: C and C++ are two different languages. Mentioning C and C++ as the same thing is somewhat like calling HTML and PHP the same thing.

Actually I think you miss the point Athox, this discussion is not about how to initialize a variable properly, its not even a discussion about setters/getters but a discussion about access modifiers, and in terms of OOP (namely inheritance) private (as PHP implements it) is bad practise.

I agree on the other hand that you should set default values in the constructor, not within the declaration, because as long as the constructor isnt called we have a class without any state, and as such it shouldnt have any values. When the constructor is called however, the class turns into an instance, and as such it can have (default) values

Actually I think you miss the point Athox, this discussion is not about how to initialize a variable properly, its not even a discussion about setters/getters but a discussion about access modifiers, and in terms of OOP (namely inheritance) private (as PHP implements it) is bad practise.

Yeah, but PHP implements that part exactly the same way as most other languages.

Either way, my argument earlier was that attributes should be as private as possible. And someone started giving me a lecture about how to match OOP with real world objects, and somewhere near that part someone else were talking about how methods should be the external communication for the object.
Can't the two posters just read each others posts and save the world? It would be great.

Having private attributes is one thing. If you want it to be changed in the subclasses, but still not from outside the class, just make the getter and setter protected. It's the correct way, no matter how you put it.

People's personal interpretations of how OOP should work are not very objective, are they? (pun intended )

Yeah, but PHP implements that part exactly the same way as most other languages.

Which doesn't mean that the other languages got it right.

Originally Posted by Athox

Either way, my argument earlier was that attributes should be as private as possible.

This isn't an argument, it's an opinion, and it heavily depends on how you define the term "private". In "most other languages" (as you put it) this keyword restricts two completely separate things: which objects may access a property, and which properties are inherited by a subclass. My point was that these are two completely separate concerns and should not be controlled by a single language construct.

Check out how is access defined in Smalltalk; here's an excerpt from the Wikipedia article:

The state an object holds is always private to that object. Other objects can query or change that state only by sending requests (messages) to the object to do so. Any message can be sent to any object: when a message is received, the receiver determines whether that message is appropriate.

In other words, you might or might not be right -- depending on the definition of the word "private", which depends on the language used. Considering we are on a PHP board, if we consider PHP you are actually wrong, as "private" inflicts inheritance restrictions which are actually harmful.

Originally Posted by Athox

And someone started giving me a lecture about how to match OOP with real world objects, and somewhere near that part someone else were talking about how methods should be the external communication for the object.

I think both of these points were mine, and as I replied above my intention wasn't to lecture anyone, and especially not you. Naturally not all methods will be public; there is a ton of uses for purely internal methods. However, an object is defined by its external behavior, which is implemented by public methods. This is the same thinking which stands behind interfaces -- an interface is actually a "type", as it defines the method signatures required for an object to be of that type.

Originally Posted by Athox

Having private attributes is one thing. If you want it to be changed in the subclasses, but still not from outside the class, just make the getter and setter protected. It's the correct way, no matter how you put it.

Your error here lies in the words "If you want it to be changed in the subclasses, but still not from outside the class" -- no attributes are changed inside or outside of a class. You don't run your methods on a class -- you always call them upon an instance of a class. The only exception are static members, but in PHP they don't differ from global variables/functions except in regards to organization of code.

I agree on the other hand that you should set default values in the constructor, not within the declaration, because as long as the constructor isnt called we have a class without any state, and as such it shouldnt have any values. When the constructor is called however, the class turns into an instance, and as such it can have (default) values

Actually, that's not strictly true, at least not in all cases. I've noticed that, when using PDOStatement->fetchObject(), the resulting object will have it's properties set BEFORE the constructor is called. While this is most likely a bug, it does show that objects do have state before the constructor is called.

In any case, there are situations where it is preferable to give properties default values, as these values can be queried using get_class_vars().

Athox is right. The attributes should be PRIVATE or PROTECTED. The methods to access them should be PUBLIC.

Sure, Athox is right, but is Athox exclusively right? If Athox was exclusively correct, then public properties would result in a parse error, no?

Just as there is more than one way to solve a math problem, there are multiple ways to solve a programming problem. My personal approach is yours, REMIYA, but there has been lots of quality software that uses others (Zend Framework, most notably).

This argument is isomorphic to KDE vs Gnome: at the end of the day, they both do exactly the same thing and it boils down to personal preference.

Actually, that's not strictly true, at least not in all cases. I've noticed that, when using PDOStatement->fetchObject(), the resulting object will have it's properties set BEFORE the constructor is called. While this is most likely a bug, it does show that objects do have state before the constructor is called.

It's not a bug, although I can't recall why it happens. (I did get a sort of explanation from Ilia once.) Calling PDOStatement::setFetchMode() with PDO::FETCH_PROPS_LATE causes properties to be set only when they're accessed. I did some experiments with this about a year ago and found that in this case they're set after __construct(), but Ilia's explanation to me suggested that they might not even be set until they're accessed like $obj->prop. (In retrospect, this seems a bit strange because that may happen long after PDOStatement::fetch() or fetchAll() spits out the object.)