|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2000-07-05 15:35 UTC] waldschrott at kiffen dot de
taken from Kristians (kk@netuse.de) mail
Uses of :: in an instance
=========================
Using :: on instance functions
------------------------------
If used in an instance of a class, :: should be able
to address a shadowed method in a superclass of the
current instances class. That is,
class a {
function somef() {
print "I am somef() in a\n";
}
}
class b extends a {
function somef() {
print "I am somef() in b\n";
}
function otherf() {
$this->somef(); // will print "I am somef in b"
a::somef(); // will print "I am somef in a"
}
}
$b_instance = new b;
$b_instance->somef(); // will print "I am somef in b"
This is useful to address a shadowed instance method
in a superclass of a class, for example when extending
an initalizing function. Note how the name of the
superclass is mentioned multiple times in b, which is
a denormalization. Changing the name of a classes superclass
will make changed in many code locations necessary.
It would be much more elegant if you had a pseudo variable
$super instead which could be used to reference a classes
superclass as in
class b extends a {
function somef() {
print "I am somef() in b\n";
}
function otherf() {
$this->somef(); // will print "I am somef in b"
$super->somef(); // will print "I am somef in a"
}
}
Alternatively, it would be useful if the class and
function names around a T_PAAMAYIM_NEKUDOTAYIM need
not be T_STRING, but can be variable references,
facilitating syntax like
class b extends a {
function somef() {
print "I am somef() in b\n";
}
function otherf() {
$c = get_parent_class(); // returns (string) "a"
$this->somef(); // will print "I am somef in b"
$c::somef(); // will print "I am somef in a"
}
}
Using :: on instance variables
------------------------------
This could be used to address shadowed instance variables
as well, but the concept of "shadowed instance variable"
is only useful when you consider static initalizers of
instance variables. That is, consider
class a {
var $some_var = "initializer in a";
}
class b extends a {
var $some_var = "initializer in b";
function showvar() {
print $this->some_var; // will print "initializer in b"
print a::some_var; // will print "initializer in a"
}
}
That would be sensible, but if it doesn't work that way,
it is of little importance.
Uses of :: outside of an instance
=================================
Class functions
---------------
Outside of an instance, :: does make sense only to address
(Objective C name:) class functions alias (Java name:)
static class member functions and (Objective C name:)
class variables alias (Java name:) static class member variables.
A class function/static class member function is a function
which can be called in a class even when no instance of
that class is available. Such functions are useful for a
variety of purposes (see any Objective C runtime documentation
or any Java handbook), but they can be emulated with plain
functions (raising namespace issues).
Example use:
class a {
function sfunction() {
print "I am sfunction in a\n";
}
}
a::sfunction(); // will print "I am sfunction in a"
A class function should be able to call other class functions,
but cannot call instance functions and therefore not refer to
$this, as there is no instance. It is of little use to create
a default instance (of a default class), raising an error
condition would be more sensible.
Class variables
---------------
A class may have class variables. Such variables are useful to
keep track of all instances of a class, for example a database
class keeping track of all database links in all database class
instance objects, or for example a Drawable class, keeping track
of all Drawable instances and providing a draw_all() class
function.
This can be emulated using a Keeper class with a single
instance and putting all instances into the Keeper after creation,
but having it in a class would still be useful in some cases.
class a {
var $class_var;
}
a::class_var = 10;
Assorted problems
=================
:: outside of classes introduces problems with variable interpolation,
as the construct is no longer introduced by $ signs. This leads at least
to strange syntax and may be creating other, more serious problems as
well.
In Smalltalk and in Objective C, classes are objects, too. Their
class is named "Metaclass" and Metaclass implements a number of
standard functions for dealing with Classes. An instance of
Metaclass is a class, and belongs to the class Metaclass as well,
terminating this recursion.
That is, in Objective C and Smalltalk
$o = new SomeClass; // $c is an instance of the class SomeClass
print $o->get_class_name(); // will print SomeClass
$c = $o->get_class(); // does not return a string, but an object
// which is the class SomeClass.
print $c->get_class_name(); // will print MetaClass
$m = $c->get_class(); // does return the class object for $c,
// which is the MetaClass object
$m->get_class(); // will print MetaClass, also.
Somehow a similar Semantic should be defined for PHP4 as well. It
need not be identical, but it should be defined to clear things up.
And it should be defined in a way that makes things function in
a sensible way (not just "because the implementation happens to be
this way").
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2026 The PHP GroupAll rights reserved. |
Last updated: Mon Jun 15 06:00:02 2026 UTC |
> KK>> The class C could have some class variables c1, c2, c3. > > What is "class variable"? How is it different from globals? In scope. A global uses up a name in the global namespace. A class variable uses up a name in the class namespace. If you think of classes as instances of a class Metaclass, this will be exactly defined. > KK>> $C::c1 = "something"; > KK>> $C::c2 = 17; > > Does this change it in all instances of class C? If so, I fear there's no > good way to do it in PHP. Think of an object $o with instance variables $o->o1, $o->o2, $o->o3, $o being an instance of class C as a hash of the following form: $o["o1"] = 1; $o["o2"] = 2; $o["o3"] = 3; $o["isa"] = &$c; // reference to Class C. $o also has the instance methods $o->im1(), $o->im2(), and $o->im3(). Think of a class C as a hash of the following form: $c["name"] = "C"; $c["im1"] = &im1(); // reference to $o->im1(); $c["im2"] = &im2(); $c["im3"] = &im3(); $c["isa"] = &$m; // reference to Class Metaclass (here called m). The class contains pointers to all methods available to instances of C. It can also contain additional pointers to functions not available to instances, but only to the class itself, and to variables not available to instances, but only to the class itself. If you change these variables, they will change for the class, or, as you say, for "all instances", as they are not kept in the instance, but in the class. $c["cm1"] = &cm1(); // marked specially so that this can be // distinguished from im1. This is a class method. $c["c1"] = 1; // marked specially, so that this can be // recognized as a class variable. Then there is the class Metaclass, here called $m. This contains all instance methods available to class objects such as $c. Such methods would be get_class(), get_parent_class(), or new(). Again, have a look at the Smalltalk model, or at Objective-C. They explain it much better than I do. http://www.amazon.com/exec/obidos/ASIN/0201136880 "Smalltalk 80: The language" http://developer.apple.com/techpubs/macosx/macosx.html "MacOS X Developer Documentation" http://developer.apple.com/techpubs/macosx/System/Documentation/Developer/Cocoa/ObjectiveC/ObjC.pdf "Objective-C Language" > KK>> $C::cm1(); > KK>> ... > KK>> > KK>> to call class methods, if possible. > > No. $var() means "take name from var, and call method by this name". Which this does. > Using such a method looks like a bad hack to me. Why to have a class if > you don't instantiate it? Just to call it a "class"? Call it "utility > library" and leave classes alone. This is not what this is about. There may be instances of class. Class variables can use useful to track instances of the class. I gave examples in a previous post, naming a database connection class like DB_Sql, keeping references to all open database handles in a class variable and a class Drawable, keeping references to all drawable instances in a class variables. Class function would then be useful to invoke actions on all instances, or to ask for values of class variables in a functional manner (accessor functions). I also stated that you could manually code a C_Keeper for each class C, create a single instance of this and use this to emulate class variables and class methods of C as instance variables and instance methods of C_Keeper. This is slightly boring, but a functioning workaround.another mail from kristian(kk@netuse.de) on "necessity of super": $super would be like $this, but referencing attributes and methods of the direct parent class of a class. Mostly, it would allow you to call methods that have been overridden, like ----- class a { function x() { print "x of a\n"; } } class b { function x() { print "preamble x of b\n"; $super->x(); print "postamble x of b\n"; } } ----- This is currently possible using namespaces as in a::x(), but that makes it necessary to denormalize the class relationship, as now the name of the superclass is coded into the subclass not only in the extends-statement, but also in many additional places. That propery of the current syntax makes changed in the class hierarchy overly hard. $super would have allowed you to chain constructors, had PHP given constructors fixed names instead of using the classname as constructor name, that is, you could have written ---- class b { function __ctor() { print "ctor of b\n"; $super->__ctor(); } } ----- Instead you get abominations as ----- class A { function A() { print "I am the ctor of a\n"; } function B() { print "I'm just an innocent function, not a ctor\n"; } } class B extends A { } $x = new b; ----- which prints ----- X-Powered-By: PHP/4.0.2-dev Content-type: text/html I'm just an innocent function, not a ctor ----- which is certainly not expected nor desired. In PHP3 and PHP4, the rule for ctors is currently "The name of the ctor function is the same as the name of the class". That would make it necessary to write a new ctor for each subclass, in order for the subclass to initalize itself properly. Had the ctor name been constant (e.g. __ctor), that wouldn't have been necessary, as the ctor would have been inherited with a proper name automatically. In PHP4, the ctor rule was amended with an exception: "If the superclass has a ctor, but the subclass has no function named just as the subclass, the superclass ctor is called despite having the wrong name." ----- kk@wwwx ~ $ Source/php3/php <?php class A { function A() { print "I am the ctor of a\n"; } } class B extends A { } $x = new B; X-Powered-By: PHP/3.0.17-dev Content-type: text/html kk@wwwx ~ $ ----- but ----- kk@wwwx ~ $ Source/php4/php <?php class A { function A() { print "I am the ctor of a\n"; } } class B extends A { } $x = new B; X-Powered-By: PHP/4.0.2-dev Content-type: text/html I am the ctor of a ----- So should it be fixed? Well, the object system in PHP currently is a mess: Classes are not types, they are just hashes with functions. Some people are currently using functionless objects as fancy array syntax, writing $o->a instead of $o["a"]. This very elegantly combines the ineffiency of objects with the lack of the ability to use array functions on them. Also, references are needed to deal properly with objects, and object networks (data structures made from objects, hashes, arrays and other container types). Additionally, ctors and dtors are handled in a suboptimal fashion or are even lacking completely. Although a mess, the current object system is a great improvement over the PHP3 non-object system: Even if not first class citizens, we do have references, and we do have an introspection API which is mostly complete, even if somewhat asystematically organized. I think the PHP object system should be fixed, and this can only be done with either breaking compatibility or by creating a second new object system with a different syntax. The fixed object system should be planned, not grown, and it should focus on dealing with componentware. That is, it should delay as many decisions as long as possible (into runtime, even call time, if possible) and it should be able to scry as many properties of an object and its class as possible at runtime. It should certainly require that instance variables are declared, because if you need $o->something for runtime-variable somethings, you may as well use $o->myhash["something"] instead. Making instance variables and instance methods fixed, declared properties of a class enables us to introduce protocols so that we can check for the presence of a predefined set of instance variables and functions with a single function call (if (conforms_to($someobj, "protocol")) and if (conforms_to(someclass, "protocol")) are true, if $someobj or someclass implement the instance vars and methods which belong to "protocol".) Proper support for serialization requires that we are able to save object networks, keeping references intact in order to keep our predefined data structures. Such serialization greatly simplifies may deeds, such as building RPC proxies, building generic interface builders, and other metaprograms. Also, second order serialization would also be useful, that is, serializing classes, for example by saving and loading the bytecode of their methods. That enables us to send not only objects, but even classes over the wire in a RPC call, or to easily deal with binary-only classes. All this requires planning and a roadmap, though, and BEFORE any additional mess is coded up and cast in stone.