Access modifier "public" not having expected results in PHP

Since I'm using "public" in the first class, I would expect that method to be available to a different object in another class, but when trying to call the say_hello() function, i get an error:

Fatal error: Call to undefined method Car::say_hello()

I thought public was supposed to allow anything in that class to be used elsewhere?  Thanks.

<?php

class Person {
	public function say_hello() {
		echo "Hello from inside the class ". get_class($this) .".<br />";
	}
	
	public function hello() {
		$this->say_hello();
	}
}


class Car {
	public $wheels = 4;
}


$ford = new Car;

$ford->say_hello();

?>

Open in new window

LVL 1
LB1234Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ray PaseurCommented:
Person::say_hello() exists.  Car::say_hello() does not.
0
Ray PaseurCommented:
But with that said, you're at the threshold of one of the great concepts in object-oriented programming: Inheritance.  Car and Person can become mutual extensions of one another.  I'll show you an example in a moment.
0
Ray PaseurCommented:
Notice line 20!  In this example, an instance of the Car class will have direct access to all of the methods of the Person class, because of the way we used Extends.  There are many reasonable uses for object inheritance (and better examples).  I'll scrape up a better one for you in a moment.

<?php // demo/temp_lb1234.php
error_reporting(E_ALL);

// SEE http://www.experts-exchange.com/Programming/Languages/Scripting/PHP/Q_28485227.html

class Person
{
	public function say_hello()
	{
		echo "Hello from inside the class ". get_class($this) .".<br />";
	}

	public function hello()
	{
		$this->say_hello();
	}
}


class Car extends Person
{
	public $wheels = 4;
}

// CREATE AN INSTANCE OF THE CAR AND CALL THE METHOD DEFINED INSIDE PERSON
$ford = new Car;
$ford->say_hello();

// SHOW THAT THE $ford OBJECT HAS WHEELS
var_dump($ford);

Open in new window

0
Cloud Class® Course: Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

LB1234Author Commented:
Person::say_hello() exists.  Car::say_hello() does not.

In this bit of code, I thought :: was to denote the use of a constant?  And that methods were called with $variable->method.
0
Ray PaseurCommented:
Try this one.  See if the relationship between the Cat and Tiger objects make sense.  Once you grasp that, you can envision how a membership object could be used in a data base.  All of the members would share common qualities (name, address, phone) but some might be basic members and some might be premium members.  Or consider automobiles.  Class Mercedes and Class Audi would both extend Class Car, but each would bring unique features on top of the basic Car paradigm.

<?php // basic_inheritance.php
error_reporting(E_ALL);
echo '<pre>';

// REF: http://php.net/manual/en/language.oop5.inheritance.php

class Feline
{
    // ALL FELINES HAVE CLAWS
    public function claws()
    {
        return "claws";
    }
}

Class Cat Extends Feline
{
    // CATS MEOW
    public function speak()
    {
        return "meow";
    }
}

Class Tiger Extends Feline
{
    // TIGERS ROAR
    public function speak()
    {
        return "ROAR!";
    }
}

// CREATE A NEW CAT AND A NEW TIGER
$tabby = new Cat;
$simba = new Tiger;

// SHOW THAT THEY BOTH HAVE CLAWS
echo PHP_EOL;
echo 'Cat: ';
echo $tabby->claws();
echo PHP_EOL;
echo 'Tiger: ';
echo $simba->claws();

// SHOW THAT THEY HAVE DIFFERENT VOICES
echo PHP_EOL;
echo 'Cat: ';
echo $tabby->speak();
echo PHP_EOL;
echo 'Tiger: ';
echo $simba->speak();

Open in new window

0
Ray PaseurCommented:
About the :: and the ->

The :: is the scope resolution operator.  In round terms, it tells PHP where to look for the property or method (what class) when it is being called statically.  Static methods and properties do not need object instantiation to be useful.

The -> is the notation we use to tell PHP where to look for the property or method when it is being called dynamically (for want of a better term).  It's used after object instantiation.

BTW, this is a good note:
http://php.net/manual/en/language.oop5.properties.php#108320
0
LB1234Author Commented:
Thanks Ray!  Taking some time to go through the links you provided so I don't ask questions that might be explained in one of them.  Quite a lot of info there, so I will comment soon.  The examples were great, although did have some questions, but reading links first.
0
Ray PaseurCommented:
It's a lot to learn, but the good news is that once you learn OOP you will never think about complex problems the same way again.  They will almost automatically break themselves down into bite-sized pieces!
0
LB1234Author Commented:
Ray, in my book "Beginning PHP 5.3" it reads the following:

"Public properties can be accessed by any code, whether that code is inside or outside the class.  If a property is declared public, it's value can be read or changed from anywhere in your script.

In my original code, I'm still not sure how this statement is being violated.
0
Ray PaseurCommented:
From the original code snippet, with comments.  Does this help?

<?php

class Person {                        // "Person" CLASS DEFINITION STARTS HERE
    public function say_hello() {
        echo "Hello from inside the class ". get_class($this) .".<br />";
    }
    
    public function hello() {
        $this->say_hello();
    }
}                                     // "Person" CLASS DEFINITION ENDS HERE


class Car {                           // "Car CLASS DEFINITION STARTS HERE
    public $wheels = 4;
}                                     // "Car CLASS DEFINITION ENDS HERE


$ford = new Car;                      // CREATES AN INSTANCE OF "Car"

$ford->say_hello();                   // THE "say_hello()" METHOD IS IN "Person" AND IS NOT IN "Car"

Open in new window

0
LB1234Author Commented:
So the definition is misleading.  Public stuff can be used by anything in the class, not anything in the entire script?
0
Ray PaseurCommented:
I think the misunderstanding may be about scope resolution, which is one of the most important tenets of OOP.  Class Person has two public methods.  They are public because the definition says so.  They are methods of the Person class because they are defined between the opening and closing curly braces of the Person class definition.  These methods can be called from anywhere in the script because they are public.  They can be called in one of two ways.

They can be called statically by writing Person::Say_hello(), since this will tell PHP to look for the say_hello() method in the Person class definition.  This will probably fail because of the use of $this, but it would be syntactically correct for a static function call.

They can be called dynamically by creating an object instance of the Person class (let's call it $p) and then writing $p->say_Hello().

You might have several say_hello() methods in a program and it's perfectly OK so long as they belong to different classes.  But PHP has to be told which class to use in order to find the say_hello() method.  Without a scope resolution operator, PHP will assume that say_hello() is a function in the main scope of the script, and will not find the say_hello() method in the classes or objects.  For obvious reasons only one say_hello() method is permitted in the main scope of the script.  More than one would be ambiguous and computers hate ambiguity.  

In the OOP5 inheritance model, when a class extends another class, it inherits all of the parent class methods and can override any/all of the methods.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
LB1234Author Commented:
Thanks again Ray, got it now!
0
Ray PaseurCommented:
Great!  Thanks for the points -- it's a really good question.
0
LB1234Author Commented:
This makes sense or doesn't depending on how one interprets the term "inside the class."  PHP means LITERALLY within the confines of the brackets themselves, NOT inside as in, within the logical grouping of a class.  And that's what was throwing me off.
0
Ray PaseurCommented:
In PHP the only "logical grouping" of a class is the set of curly brackets.  Same thing for a function:

function thing()
{
    /* THIS IS INSIDE THE "Thing() FUNCTION */
}
/* THIS IS OUTSDE THE FUNCTION, AND HAS A DIFFERENT SCOPE */
0
LB1234Author Commented:
Clears as day now thanks to your explanations.  I don't think my book was explicit enough about what it meant by "inside a class."
0
Ray PaseurCommented:
Remember that when you write your book!

:-)

Ray
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.