[PHP] Extenden/Overriden van statisch property

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik heb de volgende code:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
class Animal
{
  protected static $color = 'Black';

  public static function getColor()
  {
    return self::$color;
  }
}

class Cat extends Animal
{
  protected static $color = 'Brown';
}

class Dog extends Animal
{
  protected static $color = 'Grey';
}
?>


Echter, ik krijg de volgende output:
PHP:
1
2
3
4
5
<?php
echo Animal::getColor(); // Black
echo Dog::getColor();    // Black (huh?)
echo Cat::getColor();    // Black (what?)
?>


Het probleem is dat static properties niet aan inheritance doen. Een bug die in PHP6 opgelost zal worden, maar daar kan ik niet op wachten :9

Iemand een idee hoe dit opgelost kan worden? Ik heb de code hierboven van http://socket7.net/article/php-5-static-and-inheritance (mijn eigen code is wat ingewikkelder), daar staat wel een 'oplossing' in de comments maar ten eerste werkt hij hier niet (er wordt $this gebruikt terwijl die context er niet is) en ten tweede vind ik het een beetje een omslachtige manier om een extra method ervoor te maken.

Mijn vraag is of iemand een werkende oplossing kent.

Acties:
  • 0 Henk 'm!

  • Orphix
  • Registratie: Februari 2000
  • Niet online
Al jaren niet meer met PHP gewerkt, maar kan je de static properties niet readonly en public maken? Je weet van tevoren toch welke class je wilt benaderen, dus heb je geen polymorphisme nodig. Wat wil je precies bereiken?

Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

Statische variabele werken inderdaad niet met overerving. Je zult static moeten weglaten. Polymorphisme werkt alleen op instances en niet op objecten. Dus of je moet $color readonly en public maken, of je zult GetColor onderdeel van de instance moeten maken.

Andere oplossingen zijn er niet. Misschien even een OO boek lezen?

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
@Orphix
Ik heb een class ProfilePeer, TagPeer en een paar andere Peer classes die allemaal dezelfde soort methods hebben zoals "getById" en "getAll". Nu heb ik dus een generieke "ObjectPeer" gemaakt met al deze methods en de eerder genoemde classes zullen dus de ObjectPeer extenden. Echter, aangezien elke class weer zijn eigen tabelnaam heeft wil ik deze variabel houden. Die tabelnaam komt dus in bijvoorbeeld TagPeer en wordt gebruikt in ObjectPeer.

@Niemand_Anders
Wat ik wil bereiken schijnt wel te kunnen in sommige andere OO talen en schijnt ook in PHP6 mogelijk te worden. Misschien dat ik de verkeerde termen heb gebruikt, maar wat ik wil bereiken is sowieso mogelijk (zie link in eerste post), maar ik vroeg me af of het nog wat mooier kon.

Voor nu ga ik waarschijnlijk toch voor de oplossing om toch een instantie te maken ook al bestaat de class uit methods die onderling niks zouden hoeven delen.

Acties:
  • 0 Henk 'm!

Verwijderd

Niemand_Anders schreef op maandag 23 juli 2007 @ 15:51:
Polymorphisme werkt alleen op instances en niet op objecten.
Leg 's uit? Bij mijn weten zijn objecten instances van een class.
(dat static methods geen weet hebben van de overervende class die ze aanroept weet ik, dus dat hoef je niet te verduidelijken. ;) )

Acties:
  • 0 Henk 'm!

  • joggie
  • Registratie: November 2004
  • Laatst online: 03-02 15:00

joggie

Wie niet gek is, is saai

Verwijderd schreef op maandag 23 juli 2007 @ 14:23:
Het probleem is dat static properties niet aan inheritance doen. Een bug die in PHP6 opgelost zal worden, maar daar kan ik niet op wachten :9
Na wat uitproberen is mijn conclusie eigenlijk dat het (volgens mij) geen bug is! Er gebeurd toch eigenlijk iets heel normaals?

De functie in de base class geeft een variabele van zichzelf terug, en die zal (inderdaad) altijd de waarde "black" hebben.
Verwijderd schreef op maandag 23 juli 2007 @ 14:23:
er wordt $this gebruikt terwijl die context er niet is
$this bestaat wel, alleen er staat niks in. Probeer het maar eens zonder $this in te vullen. Ook dan vindt je alleen de waarde "black".

Zodra je hetvolgende doet:
PHP:
1
2
3
4
5
<?php
   echo Animal::getColor(); // Black
   echo Dog::getColor();    // Black (huh?)
   echo Cat::getColor();    // Black (what?)
?>

Voer je drie keer de functie getColor() uit die zich in de base klasse Animal bevindt. Deze op zijn beurt retourneert de waarde van het $color attribuut dat zich alle drie de keren in de base klasse bevindt.

In het geheugen heb je wel te maken met de andere $color attributen, die netjes overgeerft worden, echter je spreekt ze nooit aan.

Joggie ;)


Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

@TS: Enig idee wat statisch inhoud? Statisch is vast, niet veranderbaar. Omdat het een vaste waarde (vergelijkbaar met een constante) kun je de waarde niet overriden.

@AfterLive: Objecten zijn class definties. Een statische methode wordt aangeroepen op het object. Pas als je het object initialiseert krijg je een instantie (instance) van het object. Pas op dat moment werkt molymorphisme. In andere talen waarbij een scheiding gemaakt wordt tussen structures en classes praat je over objecten. Een en ander heeft te maken hoe objecten op de heap en stack worden geplaatst.

code:
1
2
3
$instance = new MyClass() // instantie van object 'MyClass'
$instance->execute(); // method call on instance
MyClass::execute(); //method call on object



Een object is een (statische) definitie van class is en daarom werken de overrides niet. Het valt mij zelfs op dat TS geen foutmelding krijgt omdat deze een statische functie aanroept van een object (cat) welke deze niet kent. Wat wel kan in getColor, is dat deze 'intern' een instantie van 'self', op de instantie daarvan getColor() aanroepen en vervolgens het resultaat terug geven.

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

  • BikkelZ
  • Registratie: Januari 2000
  • Laatst online: 21-02 08:50

BikkelZ

CMD+Z

If you treat it like a dog, it will bark like a dog.

Stel je voor dat je een array hebt met allerlei instanties van verschillende classes die je base class extenden. En er zit een instantie van een class tussen die je niet verwacht, Guppy extends Animal bijvoorbeeld. Dat kan hele rare dingen opleveren.

Ooit een fel oranje hond gezien die onder water leeft?
Aangezien een guppy twee vinnen heeft, betekent dat hij kan lopen omdat hij minstens twee ledematen heeft?
Wel blijft het bijvoorbeeld interessant om te weten of het dier nog leeft, ongeacht wat voor beest het is. Een guppy is bijvoorbeeld niet dood daar waar we een hond nog levend noemen.

Als je iets anders wilt voor bijvoorbeeld de klasse Dog of Guppy, moet je eigenlijk ook meteen die methode overschrijven. Wat ook een veel beproefde methode is, is om bij het creeren van een instantie via de constructor zaken in te stellen of de constructor van de parent class aan te roepen met een vaste colour parameter.

Wat dat betreft vind ik PHP weer wat zwakjes ten opzichte van andere talen, geen method overloading :(

iOS developer


Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Mwoah, met default parameters kom je aardig in de buurt van overloading.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Acties:
  • 0 Henk 'm!

  • BikkelZ
  • Registratie: Januari 2000
  • Laatst online: 21-02 08:50

BikkelZ

CMD+Z

Grijze Vos schreef op maandag 30 juli 2007 @ 10:35:
Mwoah, met default parameters kom je aardig in de buurt van overloading.
Tuurlijk, maar je kunt niet als eerste parameter een instantie van het object Connection meegeven en anders maar gewoon alle strings die je nodig hebt om een verbinding te maken, zonder dat je daar weer eerst op gaat zitten checken.

iOS developer


Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Dat klopt, maar dat is gewoon omdat het een dynamically typed paradigma is.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Acties:
  • 0 Henk 'm!

  • BikkelZ
  • Registratie: Januari 2000
  • Laatst online: 21-02 08:50

BikkelZ

CMD+Z

Grijze Vos schreef op maandag 30 juli 2007 @ 11:39:
Dat klopt, maar dat is gewoon omdat het een dynamically typed paradigma is.
Je zou dat weer met (werkende) type hints en eventueel variabeleklassen als String en Int kunnen omzeilen binnen een taal met dynamische variabelen natuurlijk. En ik denk dat het daar toch vroeg of laat heen gaat, dat er steeds meer eigenschappen van een static typed language binnendringen in PHP, en je misschien wel de optie blijft houden om gewoon een onbestemd varretje te declareren voor backwards compatibility.

iOS developer

Pagina: 1