I am trying to write a PHP class in which I change the visibility of a few methods from protected to public. I believe I remember you can do this in C++, but I did a few searches and I am not coming up with anything for that in PHP. Does anyone know if this is even possible in PHP?
For example, suppose this class:
class ABC {
protected function foo() {
// Do something
}
}
class DEG extends ABC {
// can I make foo public now?
}
You can change the visibility of members when deriving from a base class like this:
class Base
{
protected function foo() {}
}
class Derived extends Base
{
public function foo() { return parent::foo(); }
}
You can also do the same with properties (redefine a protected property as public).
However, be aware that if the base property is private then you will not actually increase its accessibility but rather declare a new property with the same name. This is not an issue with functions, as if you tried to call a private base method you would immediately get a runtime error.
You can overwrite a method in a derived class to highten it´s visibility (e.g. protected->public). Make the new function return it´s parent.
You cannot do so to limit it´s visibility (e.g. public->protected), but you can implement a method that checks the backtrace for the caller and thwors an exception if it´s a foreign class.
You can always use the reflection API to do all kinds of changes to the visibility.
Yes, it can be done. Quoting from PHP manual..
The visibility of a property or method can be defined by prefixing the
declaration with the keywords public, protected or private. Class
members declared public can be accessed everywhere. Members declared
protected can be accessed only within the class itself and by
inherited and parent classes. Members declared as private may only be
accessed by the class that defines the member.
And the example from there as well..
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private
Edit : Yes, you can change visibility of public and protected members. Another example from PHP manual..
/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// We can redeclare the public and protected method, but not private
protected $protected = 'Protected2';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj2 = new MyClass2();
echo $obj2->public; // Works
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Shows Public, Protected2, Undefined
?>
Related
I am now really confused about the following:
class A {
public function setPropertyValue($prop, $val) {
$this->$prop = $val;
}
}
class B extends A {
private $foo;
}
$obj = new B();
$obj->setPropertyValue("foo", "whatever"); // Fatal error: Uncaught Error: Cannot access private property B::$foo
Why and what is the point of not being able to access the private property since it is a property of B object that was instantiated and that the method is called on?
The error would make sense if it were the other way around: $foo being a private property of A and therefore not visible through inheritance to B.
I just cannot figure out why would this behavior be useful.
Private is only for the class instance using it. If you want to make it available for child or parent classes, but keep it unavailabe for public, make it protected.
class A
{
public function setPropertyValue($prop, $val)
{
$this->$prop = $val;
}
}
class B extends A
{
protected $foo;
}
$obj = new B();
$obj->setPropertyValue("foo", "whatever");
Per OOP principles:
The visibility of a property, a method or a constant can be defined by prefixing the declaration with the keywords public, protected or private.
Class members declared public can be accessed everywhere.
Members declared protected can be accessed only within the class itself and by inheriting and parent classes.
Members declared as private may only be accessed by the class that defines the member.
private - the property or method can ONLY be accessed within the class
You can't access or set a private property from anywhere else except the class it is created.
The only way of working with a private property in a class is by modyfying it in a public method of the same class.
I have recently started OOP in PHP and I am on visibility concept (public, protected, private). Here I'm confused about protected visibility. Protected members can only be accessible within the declaring clas or a subclass or child class. I have this example on PHP's site:
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
class MyClass2 extends MyClass
{
// We can redeclare the public and protected method, but not private
protected $protected = 'Protected2';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj2 = new MyClass2();
echo $obj2->public; // Works
echo $obj2->protected; // Fatal Error
echo $obj2->private; // Undefined
$obj2->printHello(); // Shows Public, Protected2, Undefined
In this code in the third last line (echo $obj2->protected; // Fatal Error) it gives fatal error. But isn't protected variable inherited into child class which is MyClass2 in this case? So why this fatal error? Can someone please enlighten me about this?
Protected members can only be accessible within the declaring class or
a subclass or child class.
You must pay attention to the within.
You're getting the fatal error because you're accessing $protected from outside both MyClass2 and MyClass.
Within means that you can access it from MyClass2 like you're doing on MyClass2::printHello() and/or MyClass::printHello() methods.
I'm a little confused about this paragraph on OO visibilty in PHP. was curious if someone could explain it to me. examples would be GREAT! my brain is not thinking clear.
http://www.php.net/manual/en/language.oop5.visibility.php
The first paragraph reads
The visibility of a property or method
can be defined by prefixing the
declaration with the keywords public,
protected or private. Class members
declared public can be accessed
everywhere. Members declared protected
can be accessed only within the class
itself and by inherited and parent
classes. Members declared as private
may only be accessed by the class that
defines the member.
how can a parent class access a childs class member?
That's how:
class A {
public function test() {
$b = new B;
echo $b->foo;
}
}
class B extends A {
protected $foo = 'bar';
}
$a = new A;
$a->test();
PHP is an interpreted language. Properties are resolved at runtime, not at the compiling stage. And access modifiers are just checked when a property is accessed.
It makes no difference if you ad-hoc inject a new (undeclared) property so it becomes public, or if you declare a protected property in an inherited class.
The private really only affects the accessibility from the outside. The ->name resolving at runtime works regardless of that. And the PHP runtime simply doesn't prope if the property declaration was made for the current object instances class. (Unlike for private declarations.)
public scope: property (method, variable etc) can be accessed from any class in any file.
class Example {
public $foo;
}
$example = new Example;
$example->foo = 3; // everything OK
private scope: property can only be accessed only by same class.
class Example {
private $foo;
}
class Child_Class extends Example {
public function some_method()
{
parent::foo = 3; // raises error
}
}
protected scope: property can only be accessed by same class or by other classes that extend it.
class Example {
protected $foo;
}
class Child_Class extends Example {
public function some_method()
{
parent::foo = 3; // this is OK
}
}
It all has to do with a technique named encapsulation, in which you must not allow a class member's state or behavior to be changed outside the class. http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)
Protected is a type of visibility which makes properties and methods declared protected available in the child classes of the declared class.
class Parent {
public $name = 'MyName';
protected $age = 20;
private $school = 'MySchool';
}
class Child extends Parent {
public function __construct() {
echo $this -> name; // valid as public
echo $this -> age; // valid as protected
echo $this -> school; // invalid as private
}
}
There you understand protected is something that used in inheritance.
Check below given code. I could not get that how it had called testPrivate() method of Class Bar class. As per my assumption it should call method from Foo class i.e. Foo::testPrivate.
Check the demo here
<?php
class Bar
{
public function test() {
$this->testPrivate();
$this->testPublic();
}
public function testPublic() {
echo "Bar::testPublic\n";
}
private function testPrivate() {
echo "<br>Bar::testPrivate\n";
}
}
class Foo extends Bar
{
public function testPublic() {
echo "<br>Foo::testPublic\n";
}
private function testPrivate() {
echo "<br>Foo::testPrivate\n";
}
}
$myFoo = new foo();
$myFoo->test(); // Bar::testPrivate
// Foo::testPublic
?>
If you want a child class to be able to overload a method defined in a parent class, that method has to be declared as protected -- and not as private.
Here, if you change your testPrivate methods definitions to :
protected function testPrivate() {
echo "<br>Bar::testPrivate\n";
}
and :
protected function testPrivate() {
echo "<br>Foo::testPrivate\n";
}
You'll get the output you expected :
Foo::testPrivate
Foo::testPublic
For more informations, you should take a look at the Visibility section of the manual -- quoting the first sentences :
Class members declared public can be
accessed everywhere. Members
declared protected can be accessed
only within the class itself and by
inherited and parent classes.
Members declared as private may
only be accessed by the class that
defines the member.
I think you misunderstand what a private method is. Foo::testPrivate() can only be call from inside Foo itself. You can acheive the behaviour you describe with a protected method. Protected means visible to the class and any classes which extend it.
I know the manual definition, but from a real life usage standpoint, what's the difference? When would you use one over the other?
EDIT:
use protected methods when you want a child class (one that extends your current (or parent) class) to be able to access methods or variables within the parent.
Here is the PHP Visibility Manual
private can be seen by no other classes except the one the variable/method is contained in.
protected can be seen by any class that is in the same package/namespace.
Code from the manual.
<?php
/**
* Define MyClass
*/
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private
/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// We can redeclare the public and protected method, but not private
protected $protected = 'Protected2';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj2 = new MyClass2();
echo $obj2->public; // Works
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Shows Public, Protected2, Undefined
?>
When you know that a variable will be used only in that class and not in any other or extending class you would name it private. So if you extend the class and mistakenly name the variable as the name of a private this would give you error and thus prevent you from making mistakes.
If you for example use many pages in your web application and all of the pages are classes that extend one single class that handles header and footer of the page (cause it's always the same) you can override for example the default title of the page which is set up in parent class with protected variable setting.
I hope this helps.