Page 2 of 2
Posted: Mon Aug 07, 2006 7:22 pm
by Ollie Saunders
Nope.
In C# you can do this:
(don't let [syntax] fool you this is C#)
Code: Select all
public class PersonAge
{
private int age; // hidden variable
public int humanAge // public acces to variable
{
get // but you are able to write functions for the getting...
{
return age;
}
set // ...and setting of it, thus :)
{
age = value;
}
}
}
// Use it like this:
PersonAge fred;
System.Echo(fred.humanAge);
fred.humanAge = 20;
You can also omit a set or get block to make a variable read or write only.
Whoo, just realised that was my 500th post XD
Posted: Mon Aug 07, 2006 7:23 pm
by Ambush Commander
Ah. I remember seeing those hanging around in PoEAA, never understood what they did though.
Posted: Fri Aug 11, 2006 9:21 pm
by santosj
ole wrote:Nope.
In C# you can do this:
(don't let [syntax] fool you this is C#)
Code: Select all
public class PersonAge
{
private int age; // hidden variable
public int humanAge // public acces to variable
{
get // but you are able to write functions for the getting...
{
return age;
}
set // ...and setting of it, thus :)
{
age = value;
}
}
}
// Use it like this:
PersonAge fred;
System.Echo(fred.humanAge);
fred.humanAge = 20;
You can also omit a set or get block to make a variable read or write only.
Whoo, just realised that was my 500th post XD
In PHP, you CAN do this, but in a different way. Each language has its own syntax, and different ways of doing the same thing. It is also possible to make a variable read or write only also.
Code: Select all
class PersonAge
{
public $age;
function __get($name)
{
if($name == 'age') {
return $this->age;
} else if($name == 'gender') {
return 'male';
}
}
function __set($name, $value)
{
if($name == 'age') {
$this->age = $value;
return true;
}
return false;
}
}
Posted: Fri Aug 11, 2006 9:35 pm
by Ollie Saunders
In PHP, you CAN do this, but in a different way
Well yes of course you
can but personally I don't like lots of switches in my code and that is what you end up with if you expand your example into something more real world:
Code: Select all
class Person
{
protected $_age;
protected $_firstName;
protected $_surname;
protected $_nationality;
protected $_id;
public function __get($name)
{
switch ($name) {
case 'age':
return $this->_age;
break;
case 'firstName':
return $this->_firstName;
break;
case 'surname':
return $this->_surname;
break;
case 'nationality':
return $this->_nationality;
break;
case 'id':
return $this->_id;
break;
default:
throw new Exception('Undefined property ' . $name);
}
}
public function __set($name, $value)
{
switch ($name) {
case 'age':
$this->_age = $value
break;
case 'firstName':
$this->_firstName = $value
break;
case 'surname':
$this->_surname = $value
break;
case 'nationality':
$this->_nationality = $value
break;
case 'id':
$this->_id = $value
break;
default:
throw new Exception('Undefined property ' . $name);
}
}
}
Obviously in the case of the example I gave there you would just do $this->{'_' . $name} = $value but this is assuming you want to write some specialist code for the setting and getting of each property.
Then also you have problems with inheritance. You can't choose which getter or setter to extend you have to override the whole __get() or __set() function; big problem. Having said all this, santosj has sucessfully drawn to may attention that this could be quite cool on a small scale. I had really just discounted it altogether.
Posted: Fri Aug 11, 2006 10:11 pm
by feyd
ole wrote:I don't like lots of switches
Who says it needs to be a giant switch? How about:
Code: Select all
class Person
{
private $age;
private $name;
private $sex;
private $parents;
private $children;
private $thoughts;
private function __get($aVar)
{
if(method_exists($this, 'get' . $aVar))
{
return call_user_func(array($this,'get' . $aVar));
}
elseif(property_exits($this, $aVar) and in_array($aVar, array('age','name','sex','parents','children'), true))
{
return $this->$aVar;
}
else
{
throw new UnknownProperty();
}
}
}
ole wrote:this is assuming you want to write some specialist code for the setting and getting of each property.
The above's fairly generic. So generic that it's basically what my Object class is built on.
ole wrote:Then also you have problems with inheritance. You can't choose which getter or setter to extend you have to override the whole __get() or __set() function;
Really?
Anyone?

Posted: Sat Aug 12, 2006 7:59 am
by Ollie Saunders
You would have inheritance problems with the switch idea, your solution solves that tho.
Feyd, you have a very good solution there. One I might steal

Posted: Sat Aug 12, 2006 8:24 am
by Ollie Saunders
Sorry for double post
I've just gone and had a look at my code to see if I could possibly implement Feyd's elegant solution. I have 26 function definitions begining with get and 8 with set. For some of them Feyd's solution would be good but for others I would rather keep them as methods and no allow them to be used as properties.
This is because when you call a method prefixed with get or set you know something is happening but when you use a property you think that you are just getting or setting that property. The difference is psychological but might change the way in which people use my objects and cause them to write code slower in performance. Not to mention there is the overhead of the __get() and __set() calls themselves.
Posted: Sat Aug 12, 2006 9:23 am
by feyd
I don't see inheritance problems in using a switch either. For example
Code: Select all
class Honda
{
// ...
protected function __get($aVar)
{
switch($aVar)
{
case 'type':
case 'drivetrain':
case 'weight':
case 'msrp':
$ret = 'unknown';
break;
case 'make':
$ret = 'Honda';
break;
default:
throw new UnknownProperty();
}
return $ret;
}
}
class Accord extends Honda
{
// ...
protected function __get($aVar)
{
switch($aVar)
{
case 'type':
$ret = 'sedan';
break;
case 'drivetrain':
$ret = 'front wheel drive';
break;
case 'weight':
$ret = '1115kg';
break;
case 'msrp':
$ret = '18221';
break;
default:
$ret = parent::__get($aVar);
}
return $ret;
}
}
Notice how "Accord" doesn't know what "make" is, but it's parent "Honda" does. The default action of "Accord's" switch returns "Honda's" response.
Posted: Sat Aug 12, 2006 9:26 am
by Ollie Saunders
Code: Select all
default:
$ret = parent::__get($aVar);
Clearly two extraordinary things are happening here. I am being extraordinarily stupid and Feyd is, as usual, being extraordinarily clever.

Posted: Sat Aug 12, 2006 10:28 am
by santosj
ole wrote:Sorry for double post
I've just gone and had a look at my code to see if I could possibly implement Feyd's elegant solution. I have 26 function definitions begining with get and 8 with set. For some of them Feyd's solution would be good but for others I would rather keep them as methods and no allow them to be used as properties.
This is because when you call a method prefixed with get or set you know something is happening but when you use a property you think that you are just getting or setting that property. The difference is psychological but might change the way in which people use my objects and cause them to write code slower in performance. Not to mention there is the overhead of the __get() and __set() calls themselves.
I doubt the overhead is all that much. You do know that there is also a _call() magic method?
However, the point is that different languages gives you different ways to do tasks. Some tasks in Java can not be converted over, Multithreading and wouldn't make sense in a web language.
The nice thing about __call() or maybe not so nice depending on how you look at it, is that it won't use the __call() magic method if there is already a method that exists with that name.
Code: Select all
class MyCall
{
function callFirst() { }
function __call($name, $parameters)
{
switch($name) {
case 'add': return $parameters[0] + $parameters[1]; break;
case 'callFirst': return "Won't be Called!"; break;
default:
throw new Exception("Method Doesn't Exist");
}
}
}
Posted: Sat Aug 12, 2006 10:31 am
by Ollie Saunders
*Scoff* of course what __call() does
However, the point is that different languages gives you different ways to do tasks.
C#'s explict getters and setters are still better.
Posted: Sat Aug 12, 2006 10:32 am
by feyd
santosj wrote:The nice thing about __call() or maybe not so nice depending on how you look at it, is that it won't use the __call() magic method if there is already a method that exists with that name.
.. unless permissions are set such that in the context being called, the method doesn't exist. e.g. a child calling a parent's private method would invoke __call() but calling a parent's protected or public method would not.