What's the meaning of ::

I’m reading that :: is used to access class methods that perform static operations, i.e., classes that do not need to be instantiated.

But I’ve also seen this in some examples: parent::constructor($value)

Don’t constructors only run when a class is instantiated?

Not when the child has its own constructor. Only one construct will be called. EDIT: This is the case for any magic method (destruct, etc)


class Parent {

  public function __construct() {
    echo "I'm a parent.\
";
  }
}

class Child extends Parent {

  public function __construct() {
    echo "I'm a child.\
";
  }
}

$t = new Child(); // I'm a child.

This is why you’ll see your class calling parent construct…


class Parent {

  public function __construct() {
    echo "I'm a parent.\
";
  }
}

class Child extends Parent {

  public function __construct() {
    parent::construct();
    echo "I'm a child.\
";
  }
}

$t = new Child(); 
// I'm a parent.
// I'm a child.

So with that being said, I’m not sure I’d say that :: is used for static methods as you can call any public function in the parent in the same way I just called the constructor.

Thanks. Your example makes sense, I think I’m getting tripped up on the syntax itself.

Here’s the original question and answer that got me Googling before posting:

Q. What’s the difference between accessing a class method via -> and via ::?
A. :: is allowed to access methods that can perform static operations, i.e. those, which do not require object initialization.

So is :: only used inside of classes to call other public functions? Or is it possible to see it in general script logic, outside of classes? And is the above answer accurate?

Well honestly I’m not an expert on it, to be able to perfectly explain the difference. The only time I use :: is to access a class name explicitly (shouldn’t be needed unless you’ve poorly named your functions to close together), call the parent, or call a static variable within that class, which is the one I commonly use:


MyClass {
  private static $var = 'foo';

  public function bar() {
    echo self::$var;
  }
}

You might be able to find something a little more useful here:
http://php.net/manual/en/language.oop5.paamayim-nekudotayim.php

To answer one of your questions. I believe you will ONLY see :: related to classes. Either accessing a function/method, a variable, or a constant. I have not seen :: used outside of an OOP approach (but that’s not to say it doesn’t exist there).

The :: is just a mechanism to separate the class name from the method/function, variable, and/or constant that is being referenced in that class. Just like -> is used to separate the class reference variable from the method/function or variable of that given reference. Or \ is used to identify Namespace separation: \Namespace\ClassName::MethodName for example.

Hope that helps clarify a few of your questions.

As I understand it, :: can also be used outside of a class to access static properties and methods without instantiating an object, eg:

class test {
 public static $foo = 'Bar';
}
echo test::$foo; // Bar

Parent is used to call the parent method.



class A {
  public function foo {
    echo 'Bah';
  }
}

class B extends A {
  public function foo {
    parent::foo();
    echo 'Bah!';
  }
}

$a = new A();
$a->foo(); // Bah

$b = new B();
$b->foo(); // Bah Bah

So with that being said, I’m not sure I’d say that :: is used for static methods as you can call any public function in the parent in the same way I just called the constructor.

parent::method isn’t the same thing as Class::method. Confused? Welcome to PHP.

Parent is a magic invocation to call the copy of the method in the parent class. For sanity reasons it should only be used by overriding method calls, though nothing in PHP stops you from using it incorrectly you will be very, very sorry if you do (I learned this one from experience. Talk about nightmare to debug code).

Outside of a child method calling the parent in an override situation, the Paamayim Nekudotayim or :: is only used in a static context as was pointed out previously in the thread.

I’m interested if you might have an example of what can go wrong by using this incorrectly?

A Hell of a lot.


class A {
  public function foo() { return 1; }
  public function bar() { return 2; }
  public function mar() { return 3; }
}

class B extends A {
  public function foo() { return parent::foo(); }
  public function bar() { return 10; }
  public function lambda() { return 4; }
}

class C extends B {
  public function foo() { return parent::mar(); }
}

Now, months later, a maintanence programmer goes in and adds a mar method to B. That’ll mess up C->foo unexpectedly. As projects grow so to does the complexity of their interactions, and allowing class methods to bypass their sister methods opens up an enormous can of worms and makes code go spaghetti crazy in short order. I know this one particularly because I made that mistake in my first year. Don’t do it.

Thank you for the advice

That’s a very good example. However the same thing can happen even if you’re using parent::method() calls “correctly”.

Consider this:


class A {
  public function foo() { return 1; }
  public function bar() { return 2; }
  public function mar() { return 3; }
}
 
class B extends A {
  public function bar() { return 10; }
  public function lambda() { return 4; }
}
 
class C extends B {
  public function foo() { return parent::foo(); }
}

C::foo() is expecting to call A::foo(). If B::foo() is defined at a later date, the behaviour of C::foo() may change unexpectedly. This may or may not be desirable. The problem the person who is making changes to the class B has, is that they don’t know whether or not any classes are extending it and what effect evenly seemingly safe changes may have on subclasses. This is an example of the Fragile base class problem

If you need complex inheritance trees it’s more likely there’s a poor separation of concerns. Do the subclasses really use all those inherited behaviours? Probably not! The real answer is to favour composition over inheritance or use interfaces.

I hardly consider that to be an unexpected change. Also, composition has problems of its own. To me its a matter of right tool for the job, and includes design patterns.

It depends what B::foo() is doing, if it alters the state of the object in some manner that C::foo() hasn’t anticipated, things in C::foo() will break. This can be avoided to a large extent by only using private variables in both classes, however knock on effects in the change in the implementation can still arise if, for instance, C::foo() is using the return value of parent::foo(). It’s a well documented issue: http://en.wikipedia.org/wiki/Fragile_base_class , http://martinfowler.com/bliki/ProtectedData.html , http://zf-william.blogspot.co.uk/2009/02/friday-13th-protected-variables-can-be.html

For classes which can be instantiated, you do so by assigning the instance to a variable.

class thing{}
$a= new thing();

Non-static methods/ properties will be changed within the instance alone.

$a->someProp=$newval;
so essentially you use -> to reach a non-static method/or property.
on the other hand static methods and properties, which by their definition cannot be instantiated , you are actually dealing directly with the CLASS itself and not an instance of the class. to reach these you use ::.

:: can be used out side the class definition, accessing a singleton object, for example. or inside a class, you may have even seen :: parent as a way to access a property at the PARENT LEVEL of a class.

hope that helps