Page 1 of 1

OOP nightmare / "visibility"

Posted: Sat Apr 18, 2009 5:15 pm
by jeffrydell
I'm new to OOP. Last week was momentous as I got my first class to actually do something.

Might as well admit this right up front... I am by no means "sold" on the way OOP php works.

That said, here's WHY I'm not very excited about jumping further in the OOpool:

(This is pseudo-code, I HIGHLY doubt the error is a matter of syntax.)


index.php:

require_once(a.class.php)
require_once(b.class.php)
require_once(c.class.php)

$a = new class A()

......

moving on to code in class A:


$b = new class B() ... which contains a 'helper method' to return values from within this class
$c = new class C() ... which contains a reference to one of class B's helper methods.

Both Class B and Class C 'extend' Class A

Class C throws these messages regarding the line with a reference to $B->helperMethod()

Notice: Undefined variable: (Name of Class B) in /path/to/Class/C.php on line 10

Fatal error: Call to a member function helperMethod() on a non-object in /path/to/Class/C.php on line 10

.....

I thought the whole idea behind OOP was to write small, reusable code that would 'play well with others' and pass info around so that a change in one place could affect necessary changes in another object's state. AND so that one object could 'ask' another for information by way of a getMethod().

So why is it so blinking difficult to get one class "see" another, much less access the data in another?

That asked, I guess the more relevant question is how does one code so that the Helper Method in class B() is actually available to be called in class C?

Thanks in advance for any guidance you can offer.

Re: OOP nightmare / "visibility"

Posted: Sat Apr 18, 2009 7:36 pm
by Christopher
jeffrydell wrote:Might as well admit this right up front... I am by no means "sold" on the way OOP php works.
:) I hate to say this sounds laughable, but no one is selling. It is like saying you are not sold on quantum mechanics. ;) Either the problems you solve are simple and Newtonian physics works fine ... or you are not able to understand quantum mechanics. There is no selling involved ... only understanding available tools.
jeffrydell wrote:Notice: Undefined variable: (Name of Class B) in /path/to/Class/C.php on line 10

Fatal error: Call to a member function helperMethod() on a non-object in /path/to/Class/C.php on line 10
Error messages usually require some code so we can see what line 10 might be...

Re: OOP nightmare / "visibility"

Posted: Sat Apr 18, 2009 8:08 pm
by jeffrydell
I hate to say this sounds laughable, but no one is selling.


So glad to have provided you with a source of entertainment.

Re: OOP nightmare / "visibility"

Posted: Sat Apr 18, 2009 9:26 pm
by Christopher
So where's the code?

Re: OOP nightmare / "visibility"

Posted: Sun Apr 19, 2009 7:12 am
by jeffrydell
Issue resolved with this helpful reply (received elsewhere):
It may well be that I'm missing something, but if class B and C are each a "child" class of A, then their objects (B's and C's, that is) would not "share" anything other than any methods and/or class variables inherited from the "parent" class A (and only those that were not defined as "private" in A). Any new variables or methods or overwritten methods would be local only to their objects, not to their siblings' objects. If you want C to directly access a B object's methods, you would probably have to either instantiate a copy of B within C, or else pass it to C, perhaps as part of the constructor:

PHP:
---------
class C extends A
{
private $b;

public __construct(B $b)
{
$this->b = $b;
}
}

$b = new B();
$c = new C($b);
$c->b->some_B_method();
---------

***************
That's all I was looking for. No quantum physics, no snarky comments. Just a simple, straightforward answer.

No, you're not 'selling' OOP php, and "buying" very well may have been a poor choice of words on my part, but I am a questioner - not a lemming. I don't do something simply because some other Bobby Big-Brain can do it. I evaluate whether other means of accomplishing a task actually have a benefit (ROI).

From what I have seen and from my learning experience with this tool, while OOP may offer increased functionalities and the ability to handle far more complex projects than would be practical with straight procedural code, I believe that php has implemented OOP in a restrictive and cumbersome way which is not at all consistent with what php set out to be.

The reason php became so wildly popular (and I would argue tremendously successful) was that it was accessible and quite straightforward to implement. Not a lot of got-chas. An "open front door" if you will. OOP, in my opinion is like a 'hall of mirrors' once you get in through that open front door ... and MAY be the reason many turn elsewhere for a development tool.

Inviting at first, not so nice once you get to know it.

Perhaps those who are the driving forces behind php should look more at making the structure of OOP a bit more developer friendly rather than trying to continue further down the path of making things more complex & restrictive. Just my thought. I do that... I think about things... and yes, I understand that thinking about the big picture may not always be popular in a place like this where process seems to be more important than product.

Re: OOP nightmare / "visibility"

Posted: Sun Apr 19, 2009 9:49 am
by skullmunky
@jeffreydell: Hi, I'm an OOP salesman. :) Actually no, I just like talking about programming.

I'm not totally clear on what the original problem was you were trying to solve, I'm just guessing based on the answer you posted. However, it sounds to me like what you're talking about is not an issue with PHP's implementation of OOP, but something fundamental to the whole philosophy behind OOP in the first place: C++, Java, Python, ActionScript, and other OOP languages probably work the same way. You generally can't access a method of one class directly from inside another class - access is through the object that owns that method, hence the name object-oriented.

Depending on what you're trying to do, you may also want to use the Paamayim Nekudotayim (::) operator to access the method in B.

Code: Select all

 
class A
{
    function method1()
    {
        echo ("this is method1 in class A<br/>");
    }
}
 
class B extends A
{
    function method2()
    {
        echo ("this is method2 in class B<br/>");
    }
}
 
class C extends A
{
    function method3()
    {
        echo ("This is method3 in class C<br/>");
        echo ("I can call methods in A, directly:<br/>");
        $this->method1();
        
        echo ("I can call methods in B as class methods, but not as object methods:<br/>");
        B::method2();
    }
}
 
 
$c=new C();
$c->method3();
 
You can use B::method2() from anywhere; being inside class C has no bearing one way or the other.

When would you use that, and when would you use the other method above? It depends on whether the method is supposed to operate on some data stored in an object of type B (a function) or if it's just a procedure.

For example, let's say all it does is print out a block of standard text. In that case, you can just use the double colons. But if you're storing some data in the classes, and the method is supposed to use that data, you do need to instantiate an object.

Lastly, if the method is something that B and C are both supposed to be able to do, and you think all other classes inherited from A should be able to do too, put the method in A. then all descendent classes can access it via $this.

You're probably even more confused than before. It all makes more sense when working with a concrete example. Good luck!

Re: OOP nightmare / "visibility"

Posted: Sun Apr 19, 2009 11:06 am
by jeffrydell
Well understood and should give me a better solution than playing "pass the object".

A workable solution is a workable solution, but yours seems to be more consistent with what I perceived SHOULD happen. At the very least, there should be a way to 'connect' with an object that is not inherited.

More specific to my situation, Class A is the Master, Class B creates some strings, Class C just needs to 'get' those strings for use in what it does. It is not possible, however, for Class C to extend B, since C MUST extend another class and multiple inheritance is a no-no, right?

Re: OOP nightmare / "visibility"

Posted: Sun Apr 19, 2009 11:57 am
by Pulni4kiya
In this situation it is possible for C to extend B.

B extends A means: B has everything that A has and a little more (defined in B).
If C extends B, then C will have everything that B has which does include everything from A.

(Sorry if I missed something and said something stupid, just trying to help)

Re: OOP nightmare / "visibility"

Posted: Sun Apr 19, 2009 12:09 pm
by jeffrydell
A calls B, B extends A.
A calls C, C extends Z (because it HAS to), but also needs stuff from B.

So the question on the table is whether C can extend BOTH Z and C.

I say no, correct? Any class can only extend one other.

Re: OOP nightmare / "visibility"

Posted: Sun Apr 19, 2009 12:16 pm
by Pulni4kiya
Yes, you are correct.

Sorry, I saw in the first post that "Both Class B and Class C 'extend' Class A" and that's why I said that.

Re: OOP nightmare / "visibility"

Posted: Sun Apr 19, 2009 12:27 pm
by jeffrydell
Perfectly fine - you're trying to address the concern and I appreciate your willingness to help!

Re: OOP nightmare / "visibility"

Posted: Sun Apr 19, 2009 7:29 pm
by Christopher
jeffrydell wrote:No, you're not 'selling' OOP php, and "buying" very well may have been a poor choice of words on my part, but I am a questioner - not a lemming. I don't do something simply because some other Bobby Big-Brain can do it. I evaluate whether other means of accomplishing a task actually have a benefit (ROI).

From what I have seen and from my learning experience with this tool, while OOP may offer increased functionalities and the ability to handle far more complex projects than would be practical with straight procedural code, I believe that php has implemented OOP in a restrictive and cumbersome way which is not at all consistent with what php set out to be.

The reason php became so wildly popular (and I would argue tremendously successful) was that it was accessible and quite straightforward to implement. Not a lot of got-chas. An "open front door" if you will. OOP, in my opinion is like a 'hall of mirrors' once you get in through that open front door ... and MAY be the reason many turn elsewhere for a development tool.

Inviting at first, not so nice once you get to know it.

Perhaps those who are the driving forces behind php should look more at making the structure of OOP a bit more developer friendly rather than trying to continue further down the path of making things more complex & restrictive. Just my thought. I do that... I think about things... and yes, I understand that thinking about the big picture may not always be popular in a place like this where process seems to be more important than product.
I don't think you understand how arrogant and insulting you sound. OOP is the way almost all professional application development is done. All modern languages. with the exception of PHP, are purely OO. Only systems programming is done in languages like C anymore. OO is used by almost all professional programmers because of the problem solving power it provides, not "simply because some other Bobby Big-Brain can do it."

Then you pronounce that the PHP Group has " implemented OOP in a restrictive and cumbersome way" and that they should "look more at making the structure of OOP a bit more developer friendly rather than ... more complex & restrictive." The assumption is that you know better that the many programmers behind PHP.

And finally you insinuate that here at DevNet "thinking about the big picture may not always be popular" and that "process seems to be more important than product." Many of the members here at DevNet make their living building products for a living. In my experience they understand the importance of both process and product to their bottom lines. And I find that there is very good advice here on the importance of both, and about thinking about both the big picture and the details.
jeffrydell wrote:A calls B, B extends A.
I don't know what A calls B means. Classes don't call classes. Class methods can call other methods.
jeffrydell wrote:A calls C, C extends Z (because it HAS to), but also needs stuff from B.
If C needs methods and properties from both B and Z by inhertance, then have B extend Z and in turn have C extend B. Then C inherits methods and properties from both Z and B.
jeffrydell wrote:So the question on the table is whether C can extend BOTH Z and C.
C can extend Z, but there is no reason for C to extend itself.
jeffrydell wrote:I say no, correct? Any class can only extend one other.
A class can only extend one other class. However, it an example you posted the code uses Composition where objects are passed to a class (they could also be created internally) and those object's methods are available to call. Composition is usually preferred to inheritance because it is often more flexible. You can proxy the methods of these composited objects to make them available in the interface of the class.

Re: OOP nightmare / "visibility"

Posted: Sun Apr 19, 2009 10:39 pm
by skullmunky
jeffrydell wrote:Well understood and should give me a better solution than playing "pass the object".

A workable solution is a workable solution, but yours seems to be more consistent with what I perceived SHOULD happen. At the very least, there should be a way to 'connect' with an object that is not inherited.

More specific to my situation, Class A is the Master, Class B creates some strings, Class C just needs to 'get' those strings for use in what it does. It is not possible, however, for Class C to extend B, since C MUST extend another class and multiple inheritance is a no-no, right?
That changes the situation a bit. Actually, I think you have to show us the actual code because otherwise you're likely to get suggestions which are all true but don't apply to the thing you actually want to do. For example, you should probably NOT use the method I posted above, because a static class method will NOT give you access to properties in an object (the strings you mention). Unless those strings are static class variables and not object properties. If you need to access strings in an object, you absolutely have to get at them through the object itself; best practices is to have a getter method that returns the value, or you can just declare them public. But the bottom line is that the object is the interface layer to both the data and the methods that it contains.

I have a suspicion that there's some underlying confusion here about the difference between classes and objects. I get the feeling that you're trying to use a class here as a single thing; but remember that classes are meant to be templates for multiple objects of the same type, and those objects are the things you (usually) work with directly. You might want to take another close read through some intro OOP tutorials ... if you're still having trouble, post your code - this kind of thing can be pretty abstract and it's much easier to talk about while looking at a specific problem.

btw, +1 on what arborint said.

but here is some more code. I can't help myself.

First, consider this class:

Code: Select all

 
class Cat
{
    public $name;
    function setName($n)
    {
        $this->name=$n;
    }
    function getName()
    {
        return $this->name;
    }
}
 
$cat1=new Cat();
$cat1->setName("joe");
echo ($cat1->getName());
 
you could also do this:

Code: Select all

 
$cat1=new Cat();
$cat1->name = "joe";
echo ($cat1->name);
 
here are things you cannot do:

Code: Select all

 
echo (Cat->name);
echo (Cat->getName());
 
why? because Cat->name does not refer to any actual cat, or its name. Cat (the class) is only a template for generating cats, not an actual cat object.

Here's another example, using the same thing your first solution post had:

Code: Select all

 
class Animal
{
 
}
 
class Cat extends Animal
{
    public $name;
    function setName($n)
    {
        $this->name=$n;
    }
    function getName()
    {
        return $this->name;
    }
}
 
class Dog extends Animal
{
    function chaseCat ($cat)
    {
        echo ("I'm going to get you, $cat->name");
    }
}
 
$cat1=new Cat();
$cat1->setName("joe");
 
$dog1 = new Dog();
$dog1->chaseCat($cat1);
 
So the question is, maybe, why can't I just say THIS instead:

Code: Select all

 
class Dog extends Animal
{
    function chaseCat ()
    {
        echo ("I'm going to get you, Cat->name");
    }
}
 
answer: because "Cat" has no name property. It only defines the structure such that cat objects will have names. Or another way of putting it: if that DID work, how could it know which cat you're talking about?

Perhaps in your code you only have one object instantiated from each of your classes, so to you, it's obvious - there's only one object, $cat1, so duh, that's the name I want. But its very common to have many objects instantiated from a class, (like many cats), and the system has to be able to handle both cases. The case where you only use one instance of a class at all is so unusual it has its own name, the Singleton Design Pattern. If you find that your code overall only has one instance of ANY class, then there may not be any reason to use classes in the first place. I could mention here that I've been programming in C++ for close to twenty years and I'm a big fan of object-oriented design, but I also frequently do PHP projects with no object-oriented design at all because it doesn't need it.

well, hope that was fun ... good luck :drunk: