[PHP] Dilemma, constructor en abstract class

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Passenger
  • Registratie: Januari 2000
  • Laatst online: 25-08 00:25
Ik heb een webapplicatie opgedeeld in modules. Gezien deze modules bepaalde functionaliteit gemeen hebben, heb ik er voor gekozen een abstract class te maken met een constructor met daarin de gemeenschappelijke code.
Nu wil ik echter in de individuele modules ook wat code standaard uitvoeren, zonder hiervoor een extra methode aan te hoeven roepen.

Ik kwam op de volgende 2 oplossingen terecht:

Oplossing 1:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
abstract class Module
{
    function __construct()
    {
        // gemeenschappelijke code  
        $this->execute();
    }   
}

class TestModule extends Module
{
    function execute()
    {
        // individuele code
    }   
}



Oplossing 2:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
abstract class Module
{
    function __construct()
    {
        // gemeenschappelijke code  
    }   
}

class TestModule extends Module
{
    function __construct()
    {
        parent::__construct();
        // individuele code
    }   
}


Nu vraag ik mij af wat nou de netste methode is om dit probleem op te lossen? Of is er zelfs nog een nettere methode?

Acties:
  • 0 Henk 'm!

  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 18-09 16:28

Bosmonster

*zucht*

Tja.. daar zijn constructors toch voor? En dus je tweede oplossing.

Acties:
  • 0 Henk 'm!

  • frickY
  • Registratie: Juli 2001
  • Laatst online: 18-09 14:42
Lijkt mij ook :? Zie het probleem niet zo eigenlijk

[ Voor 53% gewijzigd door frickY op 11-01-2006 12:06 ]


Acties:
  • 0 Henk 'm!

  • MeIsTwisted
  • Registratie: November 2001
  • Laatst online: 28-07-2023

MeIsTwisted

not a Twisted mind

* MeIsTwisted zou ook voor de 2e gaan.

zo gaat in java ook ongeveer

[ Voor 34% gewijzigd door MeIsTwisted op 11-01-2006 12:07 ]

Multimonitor is relax :P


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Nu online
Ik vind het zowiezo niet netjes om je class al direct bepaalde dingen te laten uitvoeren in je constructor.
Je constructor zou er moeten zijn voor initializatie etc... maar niet om daarin al direct 'taken' uit te voeren.

Je eerste oplossing vind ik dus maar niks.
De tweede is al heel wat beter; mits je dus je constructor beperkt tot 'initialisatie' stuff etc... en geen 'taken' laat uitvoeren.

(Moet een abstracte class eigenlijk een constructor hebben.... )

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Passenger
  • Registratie: Januari 2000
  • Laatst online: 25-08 00:25
whoami schreef op woensdag 11 januari 2006 @ 12:07:
Ik vind het zowiezo niet netjes om je class al direct bepaalde dingen te laten uitvoeren in je constructor.
Je constructor zou er moeten zijn voor initializatie etc... maar niet om daarin al direct 'taken' uit te voeren.

Je eerste oplossing vind ik dus maar niks.
De tweede is al heel wat beter; mits je dus je constructor beperkt tot 'initialisatie' stuff etc... en geen 'taken' laat uitvoeren.

(Moet een abstracte class eigenlijk een constructor hebben.... )
Nouja, met bepaalde 'taken' bedoel ik idd voornamelijk initialisatie.

Een constructor in een abstracte klasse gebruiken is toch niet zo vreemd? Ik wil namelijk ook een aantal dingen initialiseren die voor alle modules gelden... Kan ik dat beter op een andere manier oplossen?

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Nu online
Nu, ik ben niet zo bekend met PHP, maar een abstracte class zorgt er gewoon voor dat je geen instanties kunt maken van die class. Je moet er dus van inheriten.
Dan heeft een constructor in die abstracte class toch weinig zin.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 19:15
@whoami: maar je maakt juist een abstracte klasse omdat je een aantal concrete klassen hebt die bepaalde eigenschappen (een bepaalde abstractie) delen. Vaak hebben die concrete klassen dus ook een gemeenschappelijke state en die wil je wel graag initialiseren via een constructor van de abstracte klasse.

Een klasse is abstract omdat 'ie niet volledig geïmplementeerd is, niet omdat 'ie helemaal geen state heeft. Als 'ie geen state zou hebben (en dus alleen een gemeenschappelijke interface definieert) zou je er in Java beter een interface van kunnen maken (maar die optie heb je in PHP natuurlijk niet).

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Nu online
Ok, het heeft idd wel nut dat die constructor er is.
Echter, het heeft geen nut dat die constructor public accessible is. Echter, ik zie in die php code geen enkele access modifier.... ?

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik vind het overigens maar raar dat je expliciet de constructor van de base class aan moet roepen. Gaat dat niet gewoon automatisch?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Andre-85
  • Registratie: April 2003
  • Niet online

Andre-85

Sid

.oisyn schreef op woensdag 11 januari 2006 @ 13:18:
Ik vind het overigens maar raar dat je expliciet de constructor van de base class aan moet roepen. Gaat dat niet gewoon automatisch?
Nee, dat gaat niet automatisch. Op het moment dat in een child class een constructer gedefinieerd is (eigenlijk overloaded), wordt de parent constructor niet meer aangeroepen en moet je dat als programmeur zelf doen.
Geldt volgens mij ook voor C++
whoami schreef op woensdag 11 januari 2006 @ 13:17:
Ok, het heeft idd wel nut dat die constructor er is.
Echter, het heeft geen nut dat die constructor public accessible is. Echter, ik zie in die php code geen enkele access modifier.... ?
Dat was ook mijn gedachte toen ik met OO in php5 begon, echter levert de volgende code dan problemen op.
PHP:
1
2
3
4
5
6
7
8
9
<?php
class A
    {
    private function __construct()
        {
        }
    }
$a = new A;
?>

Dit resulteert in: Fatal error: Call to private A::__construct() from context '' in /home/apollux/public_html/test/access_modifier_constructor.php on line 8

Blijkbaar gaat php ervan uit dat het maken van een instance hetzelfde is al een call naar construct of iets dergelijks :?

[ Voor 52% gewijzigd door Andre-85 op 11-01-2006 13:37 ]

Lorem
Whenever we feel the need to comment something, we write a method instead. - Martin Fowler
People who think they know everything really annoy those of us who know we don't - Bjarne Stroustrup


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Andre-85 schreef op woensdag 11 januari 2006 @ 13:25:
[...]

Nee, dat gaat niet automatisch. Op het moment dat in een child class een constructer gedefinieerd is (eigenlijk overloaded), wordt de parent constructor niet meer aangeroepen en moet je dat als programmeur zelf doen.
Geldt volgens mij ook voor C++
Nee, en ook niet voor Java, C# of VB. Omdat het onzin is (tenzij je natuurlijk specifieke parameters mee moet geven aan die constructor, maar doe je dat niet en er bestaat een versie zonder parameters dan wordt die automatisch aangeroepen, anders krijg je een compile error). Een class heeft een bepaalde staat, voordat de constructor uitgevoerd is is ie ongedefinieerd omdat je alle members dan nog niet juist hebt geinitialiseerd. Het runnen van een constructor is dan ook cruciaal voordat je het object kunt gebruiken. Als je afleidt van zo'n class, dan heb je ook weer een constructor nodig om de staat van het toegevoegde gedeelte van de class goed te initialiseren, maar het initialiseren van de staat van de base moet nog steeds door de constructor van base gedaan worden, en dit zou je niet mogen omzeilen. Dat is gewoon vragen om problemen.

(En om deze reden is het ook discutabel om vanuit de constructor/destructor van een base class een polymorphe functie aan te roepen die wordt geimplementeerd door een derived class, omdat de constructor van die derived class dan nog niet uitgevoerd is.)
Dat was ook mijn gedachte toen ik met OO in php5 begon, echter levert de volgende code dan problemen op.
PHP:
1
2
3
4
5
6
7
8
9
<?php
class A
    {
    private function __construct()
        {
        }
    }
$a = new A;
?>

Dit resulteert in: Fatal error: Call to private A::__construct() from context '' in /home/apollux/public_html/test/access_modifier_constructor.php on line 8

Blijkbaar gaat php ervan uit dat het maken van een instance hetzelfde is al een call naar construct of iets dergelijks :?
Logisch, hij moet ook protected zijn, niet private. De access modifier van de constructor geeft aan wie 'm mag constructen. Is ie public dan mag niemand dat, bij private mogen instances alleen vanuit de scope van die class zelf gemaakt worden, en bij protected mogen subclasses van die class 'm dus aanroepen.

[ Voor 13% gewijzigd door .oisyn op 11-01-2006 14:25 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Nu online
.oisyn schreef op woensdag 11 januari 2006 @ 14:02:
[...]

(En om deze reden is het ook discutabel om vanuit de constructor/destructor van een base class een polymorphe functie aan te roepen die wordt geimplementeerd door een derived class, omdat de constructor van die derived class dan nog niet uitgevoerd is.)
In .NET is het zowiezo geen goed idee om dat te doen, aangezien het in vele gevallen tot fout gedrag zal leiden. (FxCop zal trouwens een melding geven als je dat wel doet).

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

In C++ kan het niet eens omdat de vtable van de derived class nog niet is ingevuld voordat de derived constructor heeft gelopen, dus zul je nooit een functie van derived aan kunnen roepen vanuit de constructor van base. Het aanroepen van een abstracte functie vanuit de constructor van base geeft een compile error, als je het via een omweg doet (door een functie aan te roepen die die polymorphe functie weer aanroept, waardoor de compiler dus niet 'weet' dat je vanuit de constructor komt) krijg je een runtime error.

[ Voor 41% gewijzigd door .oisyn op 11-01-2006 14:19 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Bosmonster
  • Registratie: Juni 2001
  • Laatst online: 18-09 16:28

Bosmonster

*zucht*

Soultaker schreef op woensdag 11 januari 2006 @ 13:12:

Een klasse is abstract omdat 'ie niet volledig geïmplementeerd is, niet omdat 'ie helemaal geen state heeft. Als 'ie geen state zou hebben (en dus alleen een gemeenschappelijke interface definieert) zou je er in Java beter een interface van kunnen maken (maar die optie heb je in PHP natuurlijk niet).
PHP5 ondersteunt overigens wel interfaces.

Acties:
  • 0 Henk 'm!

  • Andre-85
  • Registratie: April 2003
  • Niet online

Andre-85

Sid

.oisyn schreef op woensdag 11 januari 2006 @ 14:02:
[...]


Nee, en ook niet voor Java, C# of VB.
[...]
Heb je gelijk in, C++ roept standaard de constructor (zonder parameters) van de base class aan. In php echter, gebeurd dit niet.
Parent constructors are not called implicitly if the child class defines a constructor. In order to run a parent constructor, a call to parent::__construct() within the child constructor is required.
Logisch, hij moet ook protected zijn, niet private.
Protected zou idd logisch zijn maar ook dat gaat niet goed in php. Zelfde code als net maar dan protected ipv private levert het volgende op: Fatal error: Call to protected A::__construct() from context '' in /home/apollux/public_html/test/access_modifier_constructor.php on line 8

Lorem
Whenever we feel the need to comment something, we write a method instead. - Martin Fowler
People who think they know everything really annoy those of us who know we don't - Bjarne Stroustrup


Acties:
  • 0 Henk 'm!

  • iain
  • Registratie: Februari 2001
  • Laatst online: 19-07-2017

iain

Full Flavor

Het is maar welke probleem je wilt oplossen denk ik. Bij oplossing 1, wil je er voor zorgen dat de gemeenschappelijke code altijd uitgevoerd wordt, bij oplossing 2, hoeft dat niet, omdat je de gemeenschappelijke code over kan slaan.

Persoonlijk ben ik ook van mening dat het handmatig starten van een constructor een beetje raar is. Deze hoort automatisch gestart te worden.

I used to be an atheist, until I realised I was god.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Andre-85: Die error klopt precies met je codevoorbeeld; als een class een protected constructor heeft mag je 'm dus niet buiten die class of buiten een subclass van die class instancen. Het ging echter om dit voorbeeld:

PHP:
1
2
3
4
5
6
7
8
9
10
11
abstract class Base
{
    protected function __construct() { }
}

class Derived extends Base
{
    public function __construct() { parent::__construct(); }
}

$a = new Derived;


De constructor van Base hoeft niet publiekelijk accessible te zijn omdat hij toch abstract is. Hij moet echter wel protected zijn anders mogen derived classes 'm niet aanroepen (waardoor hij nooit geconstruct zal kunnen worden, omdat je 'm moet deriven aangezien hij abstract is)

[ Voor 38% gewijzigd door .oisyn op 11-01-2006 14:30 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Andre-85
  • Registratie: April 2003
  • Niet online

Andre-85

Sid

Ok duidelijk. Had ik het even niet goed begrepen, sorry ;)

Lorem
Whenever we feel the need to comment something, we write a method instead. - Martin Fowler
People who think they know everything really annoy those of us who know we don't - Bjarne Stroustrup


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

@whoami: een abstracte classe betekent idd simpelweg dat hij 'nog niet geheel geimplementeerd is', evenals een interface niet geimplementeerd is. Dit betekent echter niet dat je ze niet kan instancen; denk aan anonieme klassen. Mooi is anders, maar het kan wel.
Andre-85 schreef op woensdag 11 januari 2006 @ 13:25:
[...]

Nee, dat gaat niet automatisch. Op het moment dat in een child class een constructer gedefinieerd is (eigenlijk overloaded), wordt de parent constructor niet meer aangeroepen en moet je dat als programmeur zelf doen.
Geldt volgens mij ook voor C++
Zoals .oisyn al zei, onzin. Afaik is de eerste regel van een constructor expliciet danwel impliciet een invocation naar de constructor van de supperclasse (e.g. super();). Daarbij is het optioneel aan jou de keuze om expliciet aan te geven welke overloaded variant je ervan gebruikt. Tenminste, zo gaat het wel bij java als ik me niet vergis, en het lijkt me bijna vanzelfsprekend dat het niet anders gaat in PHP.

Even getest iig met java:

Base.java
Java:
1
2
3
4
5
6
7
8
9
package got;

public abstract class Base
{
    public Base()
    {
        System.out.println("Base constructor invoked.");
    }
}


Extension.java
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package got;

public class Extension extends Base
{

    public Extension()
    {
        System.out.println("Extension constructor invoked");
    }

    public static void main(String[] args)
    {
        Extension e = new Extension();
        System.out.println("-----");
        Base b = new Base() { }; //anonieme implementatie voor whoami ;)
    }
}


Het resultaat van het draaien van de main method van Extension.java:
code:
1
2
3
4
Base constructor invoked.
Extension constructor invoked
-----
Base constructor invoked.


Ik kan het hier nu even niet zo snel met PHP testen.

EDIT: Damn you oisyn ;), spuit 11 voor mij ;)

[ Voor 14% gewijzigd door prototype op 11-01-2006 14:42 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

In PHP moet je dat blijkbaar dus wél zelf doen. Geheel in de verwachtingen van PHP overigens, die op wel meer punten behoorlijk mis-designed is ;) /rant

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

.oisyn schreef op woensdag 11 januari 2006 @ 14:36:
In PHP moet je dat blijkbaar dus wél zelf doen. Geheel in de verwachtingen van PHP overigens, die op wel meer punten behoorlijk mis-designed is ;) /rant
Weer een reden voor mij om daar zo ver mogelijk van uit de buurt te blijven ;)

Acties:
  • 0 Henk 'm!

  • Passenger
  • Registratie: Januari 2000
  • Laatst online: 25-08 00:25
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
abstract class Base
{
    public function __construct()
    {
        echo "Base constructor invoked.";    
    }    
}

class Extension extends Base
{
    public function __construct()
    {
        echo "Extension constructor invoked";
    }    
}

$extensions = new Extension();


output:
code:
1
Extension constructor invoked


In PHP werkt het dus NIET zo.

Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

Passenger schreef op woensdag 11 januari 2006 @ 14:39:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
abstract class Base
{
    public function __construct()
    {
        echo "Base constructor invoked.";    
    }    
}

class Extension extends Base
{
    public function __construct()
    {
        echo "Extension constructor invoked";
    }    
}

$extensions = new Extension();


output:
code:
1
Extension constructor invoked


In PHP werkt het dus NIET zo.
Spuit 11 ;)

Acties:
  • 0 Henk 'm!

  • sys64738
  • Registratie: Oktober 2002
  • Laatst online: 13:50

sys64738

Moderator Foto & Video

Press play on tape

Blijkbaar gaat php ervan uit dat het maken van een instance hetzelfde is al een call naar construct of iets dergelijks :?
Ja ik weet niet hoor maar dat is toch 100% pure OO. Als je een object aanmaakt wordt altijd de constructor aangeroepen. Als je een class een private constructor geeft, kan niemand (behalve de class zelf) een instance ervan aanmaken. Dit kan handig zijn als je dat niet wilt. Dan moet je (in java altans) een static method toevoegen die een instance van het object teruggeeft (bv. MyClass.getInstance() )

edit: foutje. Class zelf kan tuurlijk wel eigen private constructor aanroepen.

[ Voor 17% gewijzigd door sys64738 op 11-01-2006 14:59 ]

Flickr | Photography 101: Skills > Patience > Gear


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

sys64738 schreef op woensdag 11 januari 2006 @ 14:43:
Als je een class een private constructor geeft, kan niemand (zelfs de class zelf niet) een instance ervan aanmaken.
Natuurlijk kan de class zelf het wel doen bij een private constructor; dat is bijvoorbeeld handig voor singletons. Een class kan sowieso altijd bij al z'n members, anders wordt private een beetje onzinnig.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

sys64738 schreef op woensdag 11 januari 2006 @ 14:43:
Blijkbaar gaat php ervan uit dat het maken van een instance hetzelfde is al een call naar construct of iets dergelijks :?

Ja ik weet niet hoor maar dat is toch 100% pure OO. Als je een object aanmaakt wordt altijd de constructor aangeroepen. Als je een class een private constructor geeft, kan niemand (zelfs de class zelf niet) een instance ervan aanmaken. Dit kan handig zijn als je dat niet wilt. Dan moet je (in java altans) een static method toevoegen die een instance van het object teruggeeft (bv. MyClass.getInstance() )
Hoho, private betekent dat het prive is voor de classe. De klasse zelf kan zichzelf wel instancen hoor. De static getInstance methode die je beschrijft is idd een toepassing ervan; singleton pattern.

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package got;

public class Singleton
{
    private static Singleton instance;
    
    private Singleton()
    {
        System.out.println("Yo");
    }
    
    public static Singleton getInstance()
    {
        if (instance == null)
        {
            instance = new Singleton();
        }
        
        return instance;
    }
}


@.oisyn: alweer spuit 11 voor mij ;) :'(

[ Voor 16% gewijzigd door prototype op 11-01-2006 14:48 ]


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Nu online
prototype schreef op woensdag 11 januari 2006 @ 14:33:
@whoami: een abstracte classe betekent idd simpelweg dat hij 'nog niet geheel geimplementeerd is', evenals een interface niet geimplementeerd is. Dit betekent echter niet dat je ze niet kan instancen; denk aan anonieme klassen. Mooi is anders, maar het kan wel.
Huh, ik zou toch wel eens een instance van een abstracte class willen zien.
Van een abstracte class kan je gewoon geen instances maken.

Dit kan bv niet:
code:
1
MyAbstractClass a = new MyAbstractClass();

De compiler zou dit moeten weigeren.

Dit kan echter wel, maar hier maak je geen instance van een abstracte class
code:
1
MyAbstractClass a = new MyInheritedFromAbstractClassClass();

waarbij MyAbstractClass dus een abstracte class is, en MyInheritedFromAbstractClassClass een class is die inherit van MyAbstractClass

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

whoami schreef op woensdag 11 januari 2006 @ 14:52:
[...]

Huh, ik zou toch wel eens een instance van een abstracte class willen zien.
Van een abstracte class kan je gewoon geen instances maken.

Dit kan bv niet:
code:
1
MyAbstractClass a = new MyAbstractClass();

De compiler zou dit moeten weigeren.

Dit kan echter wel, maar hier maak je geen instance van een abstracte class
code:
1
MyAbstractClass a = new MyInheritedFromAbstractClassClass();

waarbij MyAbstractClass dus een abstracte class is, en MyInheritedFromAbstractClassClass een class is die inherit van MyAbstractClass
Kijk even op de vorige pagina, daar heb ik een code example geplaatst van een anonieme implementatie. Het komt er op neer dat je terplekke de abstracte classe voorziet van z'n volledige implementatie, i.e. bij instancen vul je de lege (abstracte) plekken in. Hetzelfde kun je doen met een interface. Beter voorbeeld:

Java:
1
2
3
4
5
6
7
8
9
10
public abstract class Base
{
    public abstract void blaat();

    public static void main(String[] args)
    {
        Base b = new Base() { public void blaat() { System.out.println("Blaat!"); } };
        b.blaat();
    }
}

[ Voor 24% gewijzigd door prototype op 11-01-2006 15:23 ]


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Nu online
Mja, ik ben het nog altijd niet met je eens.

In je code-sample maak je nu geen instance van die abstracte 'Base' class, maar maak je een instance van een anonymous type, dat een inherited type is van je abstracte Base class. Je maakt geen instantie van Base.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

whoami schreef op woensdag 11 januari 2006 @ 15:28:
Mja, ik ben het nog altijd niet met je eens.
Dat kan ;)
In je code-sample maak je nu geen instance van die abstracte 'Base' class, maar maak je een instance van een anonymous type, dat een inherited type is van je abstracte Base class. Je maakt geen instantie van Base.
Mjah, ik heb denk ik de verkeerde woordkeuze gebruikt, wat je zegt klopt, maar het effect echter is dat die anonymous type enkel voor die instance van Base is, wat discutabel neerkomt op het 'instancen van een abstracte classe/interface'.
Simpelweg omdat de classe gedefinieerd is als abstract, wil nog niet zeggen dat deze niet geinstanced kan worden in implementatie. Op de vorige pagina gaf ik een voorbeeld van een abstracte classe die enkel concrete methodes bevat; een anonymous type die verder niets override of overload, en dus in feite Base voor de rest met rust laat, voldoet dan toch? ;)

[ Voor 40% gewijzigd door prototype op 11-01-2006 15:39 ]


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Nu online
prototype schreef op woensdag 11 januari 2006 @ 15:33:
[...]
Simpelweg omdat de classe gedefinieerd is als abstract, wil nog niet zeggen dat deze niet geinstanced kan worden in implementatie. Op de vorige pagina gaf ik een voorbeeld van een abstracte classe die enkel concrete methodes bevat; een anonymous type die verder niets override of overload, en dus in feite Base voor de rest met rust laat, voldoet dan toch? ;)
Tja, maar dan is het zowiezo je abstracte class niet meer.
Daarom denk ik dat het handig is als je de constructor van je abstracte class niet public maakt maar protected.
Ik denk dan - niet getest - dat je dan geen anonymous type zal kunnen instantiaten die niets overrided. Je anonymous type zal dan imho tenminste een publieke constructor moeten hebben.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

prototype schreef op woensdag 11 januari 2006 @ 15:33:
Simpelweg omdat de classe gedefinieerd is als abstract, wil nog niet zeggen dat deze niet geinstanced kan worden in implementatie. Op de vorige pagina gaf ik een voorbeeld van een abstracte classe die enkel concrete methodes bevat; een anonymous type die verder niets override of overload, en dus in feite Base voor de rest met rust laat, voldoet dan toch? ;)
Maar het is nog altijd geen Base, hij overerft er slechts van. Of je nou een volledige klasse definieert die overerft van Base of je gebruikt syntactische suiker die je toestaat een klasse in-place te definieren, het blijft een afgeleide klasse van een abstracte class, en die abstracte class is niet degene die je zojuist geinstanced hebt :)
whoami schreef op woensdag 11 januari 2006 @ 15:39:
Daarom denk ik dat het handig is als je de constructor van je abstracte class niet public maakt maar protected.
Waarom is dat 'handig'? In het geval van een abstracte class is een public constructor is niet anders dan een protected constructor. Je hebt namelijk niets aan die public access aangezien je 'm toch niet kan instantieren zonder 'm te subclassen.. Beide gevallen worden dus ook identiek; je kunt met de een niet meer dan de ander.

[ Voor 37% gewijzigd door .oisyn op 11-01-2006 16:51 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Nu online
Het zorgt er gewoon voor dat je niet dit kunt doen:

code:
1
Base b = new Base() {};


Dit zal je echter zowiezo al niet kunnen doen als je abstracte class een abstract member heeft.
(Echter, als je abstracte class een aantal virtual methods heeft, die gewoon een NotImplementedException gooien, zal je dat wel kunnen doen. En ik kan me niet voorstellen dat je wilt dat dit mogelijk is; waarom heb je anders je class abstract gemaakt). Het is gewoon een extra 'veiligheid' tegen dergelijke 'truken'.

[ Voor 47% gewijzigd door whoami op 11-01-2006 17:43 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Gwaihir
  • Registratie: December 2002
  • Niet online
Ik zie het bezwaar tegen oplossing 1 ook niet zo eigenlijk. Roep lekker twee methods aan: een init_algemeen en een init_individueel. Maak wel even een (in elke sub-class te overriden) lege init_individueel aan in de base-class natuurlijk. In de sub-classes hoef je dan geen (nieuwe) constructor meer op de nemen, maar alleen die init_individueel, wanneer nodig.
.oisyn schreef op woensdag 11 januari 2006 @ 14:02:
[...]


Nee, en ook niet voor Java, C# of VB. Omdat het onzin is (tenzij je natuurlijk specifieke parameters mee moet geven aan die constructor, maar doe je dat niet en er bestaat een versie zonder parameters dan wordt die automatisch aangeroepen, anders krijg je een compile error). Een class heeft een bepaalde staat, voordat de constructor uitgevoerd is is ie ongedefinieerd omdat je alle members dan nog niet juist hebt geinitialiseerd. Het runnen van een constructor is dan ook cruciaal voordat je het object kunt gebruiken. Als je afleidt van zo'n class, dan heb je ook weer een constructor nodig om de staat van het toegevoegde gedeelte van de class goed te initialiseren, maar het initialiseren van de staat van de base moet nog steeds door de constructor van base gedaan worden, en dit zou je niet mogen omzeilen. Dat is gewoon vragen om problemen.
Hoe zorg je er in die talen dan desgewenst voor dat een constructor van de base-class NIET wordt uitgevoerd (override door de constructor van de sub-class)?

[ Voor 15% gewijzigd door Gwaihir op 11-01-2006 18:21 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dat kan niet en dat mag ook niet imho, je brengt het hele object in een ongedefinieerde staat omdat z'n members niet zijn geinitialiseerd, en jij daar eigenlijk niet bij mag (aangezien die members meestal private zijn).

Je maakt een T, dus dan moet de constructor ook T uitgevoerd worden, anders is het gewoon geen T.

[ Voor 19% gewijzigd door .oisyn op 11-01-2006 19:05 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

whoami schreef op woensdag 11 januari 2006 @ 17:41:
Het zorgt er gewoon voor dat je niet dit kunt doen:

code:
1
Base b = new Base() {};
Natuurlijk wel, in die derived class definieer je geen constructor dus krijg je een default public constructor, dus mag je dat type instantieren.

[ Voor 11% gewijzigd door .oisyn op 11-01-2006 19:16 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Ik meen me te herinneren dat bij bijv. Object Pascal je ook de cocnstructor van de parent dient aan te roepen. (Inherited Create).

Ik zie niet in waarom deze aanpak meteen als slecht bestempeld wordt; het ligt gewoon niet in julie verwachtingen..

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


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik zie niet in waarom deze aanpak meteen als slecht bestempeld wordt
Dan moet je mijn reacties in deze draad nog even lezen, want ik heb toch duidelijke argumentatie gegeven dacht ik zo. En niet omdat "mijn" taal het nou toevallig wel zo doet zoals ik wil.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • iain
  • Registratie: Februari 2001
  • Laatst online: 19-07-2017

iain

Full Flavor

Grijze Vos schreef op woensdag 11 januari 2006 @ 19:17:
Ik zie niet in waarom deze aanpak meteen als slecht bestempeld wordt; het ligt gewoon niet in julie verwachtingen..
Omdat je zekerheid wilt bij de abstract class dat bepaalde dingen gedaan worden. In het geval van Passenger gaat het om een module. Als een module geladen wordt, wil je er zeker van zijn dat er verbinding gemaakt wordt met een db (oid). Dat weet je dus niet. Wat is dan de meerwaarde van een abstracte class? Dat je verplicht een aantal methods te implementeren? Maar die hoef je niet te vullen! Je weet dus niet dat er aan bepaalde voorwaarden voldaan wordt. Dat is rot. Goed, als je het weet, kan je er rekening mee houden en zelf een implementatie maken dat het feest alleen doorgaat als de constructor gedraaid is, maar dat lijkt mij overbodig...

I used to be an atheist, until I realised I was god.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Euh Mellon, 'abstract' heeft niets met de opmerking van Grijze Vos te maken, het gaat puur om het zelf aan moeten roepen van de base constructor. Of de klasse nou abstract is of niet :).

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • iain
  • Registratie: Februari 2001
  • Laatst online: 19-07-2017

iain

Full Flavor

.oisyn schreef op woensdag 11 januari 2006 @ 19:33:
Euh Mellon, 'abstract' heeft niets met de opmerking van Grijze Vos te maken, het gaat puur om het zelf aan moeten roepen van de base constructor. Of de klasse nou abstract is of niet :).
ik breng hem even wat meer ontopic ;)

maar los van dat, bij een abstracte class geldt óók nog eens mijn argument... of ben je het daar niet mee eens?

I used to be an atheist, until I realised I was god.


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

.oisyn schreef op woensdag 11 januari 2006 @ 16:47:
[...]


Maar het is nog altijd geen Base, hij overerft er slechts van. Of je nou een volledige klasse definieert die overerft van Base of je gebruikt syntactische suiker die je toestaat een klasse in-place te definieren, het blijft een afgeleide klasse van een abstracte class, en die abstracte class is niet degene die je zojuist geinstanced hebt :)
Hehe, het erft ervan over, dus technisch gezien is het wel degelijk EEN Base, daar het aan de klassenspecificatie voldoet; signatuurbehoud is gehandhaafd, maar dat zegt uiteraard niets over de implementatie. Ik begrijp wat je bedoelt en ik spreek het ook echt niet tegen, maar wat je aanhaalt was niet zozeer mijn punt om mee te beginnen. Het spreekt voor zich dat DE abstracte classe niet te instancen is, daar het abstract is en dus evt abstracte members kan bevatten.
Ik zeg alleen dat het wel mogelijk is om een abstracte classe op de manier van anonieme implementatie te 'instancen' is. Dit was qua bewoording misschien ongelukkig gekozen, 'k hoop dat met de quotjes en uiteenzetting te verhelderen ;). Het is dan zoals al eerder gezegd technisch gezien niet DIE abstracte classe waar je een instance van hebt, maar van een anonymous type die ervan erft en eventueel abstracte members voorziet van concrete implementatie. Mijn punt is hierbij in het bijzonder, dat die anonymous type die je in-place definieert, enkel voor die instantie geldt en in sommige situaties (in het geval dat er geen abstract members zijn in de classe op de classe zelf na) dan kun je een imho 'gelijkwaardig' effect bewerkstelligen als concrete classe instancen, door een 'lege' anonymous classe te definieren. In het bijzonder is de -zoals de naam al zegt- anonymous type ook echt anoniem en daarmee niet te achterhalen voor eventuele andere instanties; de subtype is anoniem, en enkel Base (en Object) is 'zichtbaar'. Dit alles komt in mijn ogen neer op zoals al gebleken is discutabel 'instancen van een abstracte classe/interface'.

[ Voor 43% gewijzigd door prototype op 12-01-2006 05:23 . Reden: typevautjes ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik snap wat je bedoelt, maar we verschillen wat dat betreft gewoon van mening: ik zie een anonieme klasse niet anders dan een klasse met een naam. Die eerstgenoemde is gewoon wat syntactische suiker voor de laaste. En hij heeft misschien dan geen naam, hij heeft weldegelijk een type (die niet gelijk maar wel compatible is met een Base), en dmv reflection zou je altijd nog meer instanties van dat type kunnen maken.

En het zou me niet verbazen dat wanneer je de naam opvraagt van die klasse dat je gewoon een unieke identifier terugkrijgt.

[ Voor 14% gewijzigd door .oisyn op 12-01-2006 11:32 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 02:21

Janoz

Moderator Devschuur®

!litemod

Birdie schreef op woensdag 11 januari 2006 @ 18:17:
Ik zie het bezwaar tegen oplossing 1 ook niet zo eigenlijk. Roep lekker twee methods aan: een init_algemeen en een init_individueel. Maak wel even een (in elke sub-class te overriden) lege init_individueel aan in de base-class natuurlijk. In de sub-classes hoef je dan geen (nieuwe) constructor meer op de nemen, maar alleen die init_individueel, wanneer nodig.
Tja, de constructor is bedoeld als 'methode die dingetjes uitvoerd zodra de classe wordt aangemaakt'. Dat jij dat graag negeert en je eigen implementatie maakt moet je zelf weten, maar je moet wel beseffen dat dat natuurlijk behoorlijk fout gevoelig is. Zo'n init methode wordt natuurlijk snel een keertje vergeten.
prototype
Ik zeg alleen dat het wel mogelijk is om een abstracte classe op de manier van anonieme implementatie te 'instancen' is.
Wat is het verschil tussen een annonieme implementatie en een benoemde implementatie? Het enige verschil is de afhandeling van de scope en dat het niet in een appart bestandje staat. Zeggen dat het een instance van Base is komt op mij over dat je zegt dat een dier een hond is omdat een hond een dier is.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

Janoz schreef op donderdag 12 januari 2006 @ 10:53:

[...]

Wat is het verschil tussen een annonieme implementatie en een benoemde implementatie? Het enige verschil is de afhandeling van de scope en dat het niet in een appart bestandje staat. Zeggen dat het een instance van Base is komt op mij over dat je zegt dat een dier een hond is omdat een hond een dier is.
Het verschil is zo nihil als je het maar maken wil. Het punt is, is dat je niet kan zeggen dat er uberhaupt sprake is van hond (de subtype is anoniem), en daarmee is enkel over Dier iets bekend. De anonieme type is een Dier, maar Dier is niet de anonieme type.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Nu online
Het anonieme type is een Dier in die zin dat het een Dier is omdat het een afgeleide is van het abstracte type Dier, echter, het is niet het abstracte type Dier.
Het is dus niet zo dat je een instantie maakt van het abstracte type Dier, maar een instantie van een anonieme afgeleide daarvan.

[ Voor 29% gewijzigd door whoami op 12-01-2006 16:04 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

.oisyn schreef op donderdag 12 januari 2006 @ 10:36:
Ik snap wat je bedoelt, maar we verschillen wat dat betreft gewoon van mening: ik zie een anonieme klasse niet anders dan een klasse met een naam. Die eerstgenoemde is gewoon wat syntactische suiker voor de laaste. En hij heeft misschien dan geen naam, hij heeft weldegelijk een type (die niet gelijk maar wel compatible is met een Base), en dmv reflection zou je altijd nog meer instanties van dat type kunnen maken.
Hoe zou dit met reflection dan in z'n werking gaan als ik vragen mag? :) Dit is namelijk nieuw voor me, en vereikingsstof kan geen kwaad dunkt me :)
De enige manier die ik nu voor ogen had, was namelijk door genoemd object te clonen, maar dat vereist in de eerste plaats Clonable en voldoet niet omdat het een shallow copy oplevert.
En het zou me niet verbazen dat wanneer je de naam opvraagt van die klasse dat je gewoon een unieke identifier terugkrijgt.
Ja, de naam van de anonieme type :) Dat zou ook zeker geen verassing zijn, aangezien deze een anonieme subtype is van zijn in dit geval abstracte supertype.

[edit]
ik heb dit zojuist even getest, en wat ik terugkrijg is het volgende:

code:
1
got.Base$1

Afaik, impliceert de $ teken toch een inner classe?

[ Voor 9% gewijzigd door prototype op 12-01-2006 16:25 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

prototype schreef op donderdag 12 januari 2006 @ 16:17:

Hoe zou dit met reflection dan in z'n werking gaan als ik vragen mag? :) Dit is namelijk nieuw voor me, en vereikingsstof kan geen kwaad dunkt me :)
De enige manier die ik nu voor ogen had, was namelijk door genoemd object te clonen, maar dat vereist in de eerste plaats Clonable en voldoet niet omdat het een shallow copy oplevert.
Elk object heeft een type, en met reflection kun je informatie voor deze types opvragen. Dat een type in een programmeertaal een naam heeft is slechts een handigheid om te onthouden en aan te geven welk type je bedoelt; het zouden ook GUIDs kunnen zijn maar dat werkt zo lastig :)

Een anonymous class definitie is gewoon een klassedefinitie als elke andere, alleen er wordt geen link naar die class in de huidige namespace aangemaakt. Dat betekent niet dat ie niet bestaat, het is voor de VM een volledig type en dus kun je met reflection een nieuwe instance van die class maken (mits hij niet abstract is uiteraard ;)), net als bij elke andere class
Afaik, impliceert de $ teken toch een inner classe?
Die $ impliceert helemaal niets, het is gewoon een teken die in een identifier niet toegestaan is, zodat je geen nameclashes kunt krijgen met bestaande niet-anonieme classes :)

[ Voor 11% gewijzigd door .oisyn op 12-01-2006 16:33 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

.oisyn schreef op donderdag 12 januari 2006 @ 16:31:
[...]


Elk object heeft een type, en met reflection kun je informatie voor deze types opvragen. Dat een type in een programmeertaal een naam heeft is slechts een handigheid om te onthouden en aan te geven welk type je bedoelt; het zouden ook GUIDs kunnen zijn maar dat werkt zo lastig :)

Een anonymous class definitie is gewoon een klassedefinitie als elke andere, alleen er wordt geen link naar die class in de huidige namespace aangemaakt. Dat betekent niet dat ie niet bestaat, het is voor de VM een volledig type en dus kun je met reflection een nieuwe instance van die class maken (mits hij niet abstract is uiteraard ;)), net als bij elke andere class
Ah, hoog tijd om die reflection api eens te bestuderen. Heb je nog tips voor beginpunten hiermee? Boeken etc...
[...]

Die $ impliceert helemaal niets, het is gewoon een teken die in een identifier niet toegestaan is, zodat je geen nameclashes kunt krijgen met bestaande niet-anonieme classes :)
Je hebt gelijk, 'k was even in de war met de conventie die de compiler hanteert voor innerclass filenames.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

prototype schreef op donderdag 12 januari 2006 @ 16:39:

Ah, hoog tijd om die reflection api eens te bestuderen. Heb je nog tips voor beginpunten hiermee? Boeken etc...
Nee, ben geen java developer ;)
Je hebt gelijk, 'k was even in de war met de conventie die de compiler hanteert voor innerclass filenames.
Nou ja, om diezelfde reden wordt het daarvoor natuurlijk ook gebruikt. Als je een class Inner in een class Outer definieert, dan krijgt ie de naam Outer$Inner. Gewoon Inner kan niet, omdat dat zou kunnen conflicteren met een andere Inner class in dezelfde package die geen inner class van Outer is. Hetzelfde geldt natuurlijk voor iets als Outer_Inner, die zou je ook zelf kunnen definieren.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • iain
  • Registratie: Februari 2001
  • Laatst online: 19-07-2017

iain

Full Flavor

nog meer OO-dilemma's voor PHP en hoe deze opgelost gaan worden in PHP6 staan op:

http://www.php.net/~deric...-the-parent-s-constructor

I used to be an atheist, until I realised I was god.


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Persoonlijk vind ik het maar vreemd dat de constructor van een base class ineens wel automatisch wordt aangeroepen als hij geen parameter interface heeft. Niet erg consequent met het geval dat je wel parameters hebt. In beide gevallen is het mogelijk (zeer waarschijnlijk zelfs) dat de constructor van de base class aangeroepen moet worden om normaal te functioneren. Een betere oplossing vind ik dan om in een class te kunnen specificeren dat de constructor aanroepen moet zijn en dat anders een (compile) error wordt gegeven.

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • Gwaihir
  • Registratie: December 2002
  • Niet online
Janoz schreef op donderdag 12 januari 2006 @ 10:53:
[...]

Tja, de constructor is bedoeld als 'methode die dingetjes uitvoerd zodra de classe wordt aangemaakt'. Dat jij dat graag negeert en je eigen implementatie maakt moet je zelf weten,
Eh? Hoezo negeer ik dat? Dat doet hij in 'mijn implementatie' toch nog steeds? Ik besteed alleen een (groot) deel van het werk uit aan een paar andere methodes. Mag een constructor volgens jou geen andere methodes aanroepen of zo? :? Wat doe jij dan als hij een tamelijk onbezonnen groot formaat blijkt te gaan krijgen? Geldt dat alleen voor het aanroepen van methoden van de eigen klasse (of parent), of mag hij volgens jou per definitie helemaal niets aanroepen (lijkt me zo'n beetje onmogelijk, maar goed)?
maar je moet wel beseffen dat dat natuurlijk behoorlijk fout gevoelig is. Zo'n init methode wordt natuurlijk snel een keertje vergeten.
Lijkt me juist minder foutgevoelig dan de tweede methode. Je kunt die init methode toch helemaal niet vergeten? Als je niets defineert wordt keurig de constructor van de base class uitgevoerd en verder niets. (Nou ja, aan het het lege stubje wordt even gesnuffeld natuurlijk ;).) Precies zoals het zou moeten.

Het risico zit voor zover ik zie in de tweede methode: als je daar lekker een constructor voor je subclass gaat defineren moet je er zelf aan denken ook (eerst) de constructor van de base class aan te roepen. Makkelijk te vergeten of verkeerdom te doen..

Dus.. de vraag staat weer open: wat is er - mede gezien de manier waarop PHP de constructor van de base class 'geneigd is over te slaan' - nu eigenlijk mis met methode 1, mits netjes uitgevoerd? (Waarmee ik bedoel dat je - zoals ik eerder poste - wel effe een te overriden 'lege' function execute in je basis klasse moet zetten.)

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Birdie schreef op dinsdag 17 januari 2006 @ 02:59:
Mag een constructor volgens jou geen andere methodes aanroepen of zo? :?
Geen methodes die geimplementeerd worden door afgeleide klassen, als je het mij vraagt. Initialisatie gebeurt in de constructor, dat die constructor een (private) method van z'n eigen class aanroept om het werk wat te verdelen is natuurlijk een heel ander verhaal en mag best. Maar initialisatie van Module begint in de constructor van Module, net als de initialisatie van TestModule zou moeten beginnen in de constructor van TestModule. Daar zijn die dingen immers voor. En in PHP valt het allemaal nogal mee, maar als je talen gaat gebruiken waarin initialisatie een belangrijk proces vormt (zoals C++) zie je al dat je niet meer om constructors heen kan.
Het risico zit voor zover ik zie in de tweede methode: als je daar lekker een constructor voor je subclass gaat defineren moet je er zelf aan denken ook (eerst) de constructor van de base class aan te roepen. Makkelijk te vergeten of verkeerdom te doen..
Klopt, daarom is het fijner als dat automatisch gebeurt of als je een fout krijgt als je het niet doet, maar het zou zo common practice moeten zijn dat je zo'n fout natuurlijk al niet maakt. Daarnaast, wat ga je doen als je van TestModule weer een klasse afleidt? Je kunt dan wel een execute() implementeren in AfgeleideTestModule, maar dan wordt die van TestModule niet meer aangeroepen. Dus dan zul je in AfgeleideTestModule::execute() weer een call moeten toevoegen naar TestModule::execute(), die je net zo goed kunt vergeten, en waar het er bovendien niet consistenter van wordt.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Maar als je base class constructor dan wel parameters vereist, dan kun je die fout net zo goed maken. Beter is om het dan in alle gevallen af te straffen.

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dus dat is een reden om voor optie 1 te gaan?
(Wat een taal beter zou kunnen doen staat hier natuurlijk los van :))

[ Voor 45% gewijzigd door .oisyn op 17-01-2006 12:06 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Nee, dat is een reden om nooit automatisch de constructor van de base class te gebruiken, behalve als een sub class zelf geen constructor definieert. Mij lijkt het verder een goede feature om dan de mogelijkheid te krijgen een sub class te verplichten de base class constructor aan te roepen als deze zelf eentje toe voegt. Zo'n slechte gedachten gang van php vind ik dat helemaal niet. Er zijn mindere punten, maar dit behoort daar imo niet toe.

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ja maar nu zit je al 3 posts je punt te herhalen terwijl niemand dat ontkent ;). Maar PHP verplicht het helemaal niet, de constructor van de base wordt nu gewoon doodleuk niet aangeroepen als je dat zelf niet doet. Daarnaast is het questionable of je zo'n verplichting ook op wilt leggen, het heet immers een default constructor in de meeste talen, die wordt aangeroepen als je überhaupt geen parameters opgeeft. Nou werk je in talen als PHP, Java en C# sowieso met new, maar in C++ kun je classes ook als value-type benaderen. Moet je dan in iedere constructor voor al je members die nodeloze redundante informatie opgeven dat je die types wilt constructen met de default constructor? Ik vind dat een beetje ver gaan.

[ Voor 81% gewijzigd door .oisyn op 17-01-2006 14:24 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 02:21

Janoz

Moderator Devschuur®

!litemod

De reden dat in PHP niet impliciet de constructor van een base class aangeroepen wordt is gewoon omdat ze het vergeten zijn. Zodra je uberhaupt over dit onderdeel na gaat denken zijn er geen valide argumenten te verzinnen om het niet te doen.

@Birdy: Ik las uit je post niet dat je die twee methoden dan vervolgens in je base constructor aan ging roepen, maar de bezwaren worden ook al door .oisyn aangestipt. Ik heb echter geen idee waar jij weghaalt dat ik beweer dat je vanuit je constructor geen andere methoden aan mag roepen. Het enige dat ik zeg is dat de constructor de verantwoordelijkheid heeft voor het initialiseren van de class. Voor het initialiseren van de derived class is dan ook de constructor van de derived class verantwoordelijk, en niet de constructor van de base class.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
@.oisyn:

Een constructor zonder parameters,die zelf is toegevoegt, is toch geen default constructor meer? De default constructor is volgens mij de constructor die automatisch wordt toegevoegt als er geen geimplementeerd is. Dat de default constructor automatisch aangeroepen wordt lijkt me logisch. Die doet verder toch vrij weinig. Maar ik vind het wel vreemd dat een constructor dan ook wordt aangeroepen als je hem wel implementeerd, eentje zonder parameters dus. (Of is dat niet zo? Dan heb ik niets gezegd :P)

Ik zou ook niet dat PHP het verplicht. Ik zei wel dat ik het goede feature vind dat je dat aan zou kunnen geven. En dat als je dan een sub class instantie construeert, zonder dat de constructor (die is gemarkeerd als vereist) van de base class wordt aangeroepen, dat dan een error wordt gegeven.

Ik heb ook wel gevallen gehad dat ik een sub class onafhankelijk van de base class wilde construeren. Ik zou het dan erg vervelend vinden als de base class constructor automatisch aangeroepen zou worden.

Maar om antwoord te geven op je vraag. Nee, dat is zeker geen reden om voor optie 1 te gaan. Initialisatie hoort in de constructor te gebeuren.

[ Voor 16% gewijzigd door Michali op 17-01-2006 18:18 ]

Noushka's Magnificent Dream | Unity


Acties:
  • 0 Henk 'm!

  • Gwaihir
  • Registratie: December 2002
  • Niet online
Janoz schreef op dinsdag 17 januari 2006 @ 15:33:
Het enige dat ik zeg is dat de constructor de verantwoordelijkheid heeft voor het initialiseren van de class. Voor het initialiseren van de derived class is dan ook de constructor van de derived class verantwoordelijk, en niet de constructor van de base class.
Ja; dat is een mooie lijnrechte logica die me zeer aanspreekt.

Toch zou het mooi zijn als (tevens / daarbinnen) in de base class een verplichting voor afgeleide klassen kan worden gecreëerd om zijn constructor aan te roepen.. (en daar komt oplossing 1 voor mijn gevoel dichter bij dan oplossing 2). Is daar wellicht al iets op te verzinnen? (Al = behalve te wachten op PHP6)

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Michali schreef op dinsdag 17 januari 2006 @ 18:15:
Een constructor zonder parameters,die zelf is toegevoegt, is toch geen default constructor meer? De default constructor is volgens mij de constructor die automatisch wordt toegevoegt als er geen geimplementeerd is.
http://www.kuzbass.ru/docs/isocpp/special.html#class.ctor
A default constructor for a class X is a constructor of class X that can be called without an argument. If there is no user-declared constructor for class X, a default constructor is implicitly declared
En doe ook maar eens een search voor "default constructor" op java.sun.com oid, de default constructor is gewoon de constructor zonder argumenten, die idd impliciet gegenereerd wordt als je helemaal geen constructors definieert (maar dat is niet de reden dat ie "default" wordt genoemd).
Ik heb ook wel gevallen gehad dat ik een sub class onafhankelijk van de base class wilde construeren. Ik zou het dan erg vervelend vinden als de base class constructor automatisch aangeroepen zou worden.
Ik vind dat heel erg klinken naar slecht design, hoe kun je een geconstructe MyWindow hebben, als de Window waarvan hij inherit nog niet geconstruct is? Die MyWindow is ook een Window, dus moet die Window geldig zijn (zelfs voordat MyWindow geldig hoeft te zijn, dit zie je ook erg terug in het design van C++ waar het runnen van constructors essentieel is). Zou je anders de situatie kunnen schetsen waarin je je bevond? Da's wel interessant :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Michali
  • Registratie: Juli 2002
  • Laatst online: 29-05 22:54
Ok, het komt idd zelden voor, net zoals dat je een andere method (want een constructor is dat net zo goed) van een base class override en niet opnieuw aanroept. Een voorbeeld is dat je met een strategy werkt waarbij je de sub class laat bepalen van welke class je instantieert. Als de base class dan automatisch wordt aangeroepen wordt gewoon een andere instantie toegekent (hij wordt dan wel voor de construtor van de sub class aangeroepen, maar het is iig niet erg efficient. Mischien is dat ook op te lossen met een template method of een factory die dat voor je regelt, maar in sommige gevallen lijkt dat niet nodig. Ook wil je soms mischien een sub class net even anders initialiseren dan de base, net als dat je soms bij een andere method gewoon de functionaliteit van de base method niet wilt gebruiken. Dan zou ik het ook vervelend vinden als hij wel ineens automatisch wordt aangeroepen als hij geen parameters heeft.

Ik heb even in mijn code gekeken, maar kan even zo snel geen voorbeeld meer vinden. Ik denk dat ik het weg gedesigned heb :P Het komt idd weinig voor, mischien is het ook niet goed om daar van afhankelijk te zijn, maar toch vind ik het vreemd dat die automatisch wordt aangeroepen, ook al heb je een constructor gedefinieert in je sub class.

Noushka's Magnificent Dream | Unity

Pagina: 1