[JAVA] Inheritance vraag

Pagina: 1 2 Laatste
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

bronce schreef op woensdag 06 april 2011 @ 12:31:
Java:
1
//knip


Dit is een goede structuur omdat:
De collectie klasse weinig afhankelijkheid heeft en weinig verantwoordelijkheid.
De collectie hoeft niet bij te houden welke klassen geopend moeten kunnen worden.
Bij instanceof moet dat wel.
Het argument dat elk object open() moet hebben is onzin want dat is hier ook niet het geval kast heeft open() en bank hoeft het niet verder te definiëren.
Jij doet echt goed je best om niet te lezen wat mensen zeggen he? Een Meubel kun je niet openen. Open() betekent niks op een Bank of een Stoel. Een functie inbouwen die niets doet gaat juist alleen maar gezeik opleveren omdat je geheid een keer een fout maakt waarmee je een Stoel probeert te openen en vervolgens geen foutmelding krijgt. Succes met dat debuggen. :X

Ik haal .oisyn's Object-argument er maar niet meer bij omdat hij het zelf al gedaan heeft, maar als je op jouw manier programmeert krijg je dus gigantische classes met absurd veel methods voor alle mogelijke interfaces die je had kunnen implementeren. Allemaal methods die niets doen en arbitrair true of false returnen. Lekker dan.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • bronce
  • Registratie: Januari 2011
  • Laatst online: 12-09 16:17
[/quote]
Maar waarom zit open() dan niet op de klasse Object?
[quote]

Omdat alles wat tussen Object en Meubel zit niet de mogelijkheid kan hebben om geopend te worden.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

bronce schreef op woensdag 06 april 2011 @ 12:37:
[...]

Omdat alles wat tussen Object en Meubel zit niet de mogelijkheid kan hebben om geopend te worden.
Ook niet alles dat tussen Meubel en Stoel zit.

[ Voor 12% gewijzigd door NMe op 06-04-2011 12:38 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • bronce
  • Registratie: Januari 2011
  • Laatst online: 12-09 16:17
Je hebt de keuze om open() te overriden doe je dat niet dan kan het niet geopend worden.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Waarom zit ie dan niet op Object?

Je ziet, je redeneert in cirkeltjes. Hij hoort niet op Object omdat je niet ieder Object open kunt doen. Maar hij mag wel op Meubel omdat je de keuze hebt om open() niet te overriden? Waarom mag hij dan niet op Object, ook daar kun je de keuze hebben om 'm niet te overriden.

[ Voor 80% gewijzigd door .oisyn op 06-04-2011 12:40 ]

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!

  • Amras
  • Registratie: Januari 2003
  • Laatst online: 11-09 19:11
NMe schreef op woensdag 06 april 2011 @ 12:38:
[...]

Ook niet alles dat tussen Meubel en Stoel zit.
Inderdaad. En als je inheritance structuur groter en groter wordt, met meer ingewikkelde meubels dan krijgt je Pianokrukje ineens wel heel veel loze methodes die er eigenlijk niet op aangeroepen mogen worden. Wat mij betreft een slecht codevoorbeeld.

Acties:
  • 0 Henk 'm!

  • bronce
  • Registratie: Januari 2011
  • Laatst online: 12-09 16:17
Waarom wel?

Dat is de meest onzinnige vraag ooit.
Waarom checkt Object niet of het een instantie van Kast is ?

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Zie mijn edit. Je bent jezelf echt enorm aan het tegenspreken. En als je dat niet eens inziet dan heb je wel echt een enorme plaat voor je kop :)

Je hebt 2 stellingen gedaan:

1. Een methode mag niet in een klasse als die methode niet opgaat voor iedere instantie van die (sub)klasse.
2. Een methode mag wel in een klasse als je ervoor kunt kiezen om 'm niet te overriden.

Volgens 1. mag open() niet in Meubel, en volgens 2. mag open() wel in Object.

[ Voor 133% gewijzigd door .oisyn op 06-04-2011 12:42 ]

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!

  • bronce
  • Registratie: Januari 2011
  • Laatst online: 12-09 16:17
Maar waarom checkt Object niet of het een instantie van Kast is om te bepalen of hij open mag?

Acties:
  • 0 Henk 'm!

  • Amras
  • Registratie: Januari 2003
  • Laatst online: 11-09 19:11
bronce schreef op woensdag 06 april 2011 @ 12:42:
Maar waarom checkt Object niet of het een instantie van Kast is om te bepalen of hij open mag?
Dat hoeft ook niet, je zou wel kunnen controleren of het object IOpenable implementeert en hem, zo ja, daarna openen. ;)

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Omdat dat geen verantwoordelijkheid van Object is, hij kan nooit weten welke subtypen er allemaal bestaan. Net zoals dat ook geen verantwoordelijkheid van Meubel is. Jij verwart de collectie van Meubels met Meubel zelf. Het zijn twee compleet verschillende dingen. Iemand die een collectie van Meubels heeft, die mag best wel checken of een instantie van een bepaald type is. Dat doen is niet ineens een verantwoordelijkheid van Meubel.

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!

  • bronce
  • Registratie: Januari 2011
  • Laatst online: 12-09 16:17
de oplossing die op het begin is aangehaald:

Java:
1
2
3
4
5
6
7
8
9
10
11
Set<Meubel> meubels = new HashSet<Meubel>();

meubels.add(new Meubel());
meubels.add(new Kast());

for (Meubel m : meubels) {
    m.plaats();
    if (m instanceof Openable) {
        ((Openable)m).open();
    }
}


nu moet de klasse die de collectie bevat bepalen of iets geopend mag worden.
in OO is het de bedoeling dat klassen zoveel mogelijk onafhankelijk zijn (ze hebben vaak een klein beetje afhankelijkheid).
Elke klassen moet ook een duidelijk doel hebben en niet veel verantwoordelijkheid.
Een Meubel (of een subklasse voor Meubels die geopend kunnen worden) moet bepalen of hij geopend mag worden niet de klasse met de collectie !!!!!!!

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

bronce schreef op woensdag 06 april 2011 @ 12:42:
Maar waarom checkt Object niet of het een instantie van Kast is om te bepalen of hij open mag?
Waar precies checkt de klasse Meubel hier datzelfde?
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
class Kamer {
    Set<Meubel> meubels = new HashSet<Meubel>();

    meubels.add(new Meubel());
    meubels.add(new Kast());

    for (Meubel m : meubels) {
        m.plaats();
        if (m instanceof Openable) {
            ((Openable)m).open();
        }
    }
}

Dit is de code die Cheatah hierboven plaatste. Meubel heeft überhaupt geen kennis van het feit dat er een Openable is, laat staan dat hij de method open() implementeert. Kast kent Openable wel en implementeert die interface ook.
bronce schreef op woensdag 06 april 2011 @ 12:49:
nu moet de klasse die de collectie bevat bepalen of iets geopend mag worden.
in OO is het de bedoeling dat klassen zoveel mogelijk onafhankelijk zijn (ze hebben vaak een klein beetje afhankelijkheid).
Elke klassen moet ook een duidelijk doel hebben en niet veel verantwoordelijkheid.
Een Meubel (of een subklasse voor Meubels die geopend kunnen worden) moet bepalen of hij geopend mag worden niet de klasse met de collectie !!!!!!!
Nee, de Kast weet of hij geopend kan worden. Hij is immers Openable. De klasse bepaalt dan ook dat het mag. De collectie controleert alleen of die bepaling er wel of niet is.

[ Voor 31% gewijzigd door NMe op 06-04-2011 12:52 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • bronce
  • Registratie: Januari 2011
  • Laatst online: 12-09 16:17
Het is ook goed dat kast die interface implementeert Dat meubel daar geen kennis van heeft is ook goed.
Maar waarom verpest je het dan door nog een check te doen in de Main klasse met de collectie?
Is het de verantwoordelijkheid van die klasse om te weten welk meubel geopend moet worden?

Acties:
  • 0 Henk 'm!

  • CodeCaster
  • Registratie: Juni 2003
  • Niet online

CodeCaster

Can I get uhm...

bronce schreef op woensdag 06 april 2011 @ 12:49:
Een Meubel (of een subklasse voor Meubels die geopend kunnen worden) moet bepalen of hij geopend mag worden niet de klasse met de collectie !!!!!!!
Zelfs zeven uitroeptekens maken dat statement niet waar. De collectie meubels moet juist wél weten welk meubel openable is, omdat de klasse meubel hier geen drol mee heeft te maken! Jij legt álle verantwoordelijkheden voor álle soorten meubels in één klasse, terwijl deze klasse juist generiek zou moeten zijn: van toepassing op alle meubels.

In de klasse Meubel zet je alleen de dingen die gelden voor alle meubels, zoals bijvoorbeeld afmetingen en gewicht, en verdere specifieke kenmerken worden per exemplaar (bijvoorbeeld Kast) bepaald.

Kun je elk meubel openen? Nee. Moet Open() dan in Meubel? Nee. Je wringt jezelf hier in de meest onmogelijke bochten om maar Open te kunnen doen op alle meubels, terwijl dit inherent onmogelijk is (zie Stoel). Het voorbeeld (foreach (Meubel m in Meubels) {m.Open(); } ) is wellicht ongelukkig gekozen, omdat je zo'n constructie niet snel zult maken. Je hebt eerder een rij kasten die je wil Open()en, en daar pas je de collectie dan eventueel ook op aan.

https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

bronce schreef op woensdag 06 april 2011 @ 12:49:
nu moet de klasse die de collectie bevat bepalen of iets geopend mag worden.
in OO is het de bedoeling dat klassen zoveel mogelijk onafhankelijk zijn (ze hebben vaak een klein beetje afhankelijkheid).
Exact. En daarom mijn opmerking dat je je af moet vragen of die collectie zo wel handig is ontworpen. Door gewoon maar open() toe te voegen op Meubel creëer je niet alleen extra (en bovendien onjuiste) afhankelijkheden, het is symptoombestreiding, want het daadwerkelijke "probleem" (voor zover het een probleem is) zit bij de code die de collectie gebruikt.

En oh ja, aangezien jij daar vatbaar voor lijkt: !!!!!!!!!!!!

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!

  • bronce
  • Registratie: Januari 2011
  • Laatst online: 12-09 16:17
Ja maar de afhankelijkheid die creëert door de verantwoordelijkheid bij de collectie te leggen is ook niet het beste ontwerp. Stel ik voeg een klasse Stoel die die wil ik sitable maken dan moet ik een Stoel maken die Sitable implementeert en sit() overriden EN je moet in je collectie een check doen naar instanceof Sitable.
Nou zijn er nog wel meer eigenschappen te bedenken dan Sitable en Openable het probleem hier is dus die afhankelijkheid als je iets wilt toevoegen of verwijderen moet dit op twee plaatsen hierdoor wordt je programma onderhoudsonvriendelijk en een onderhoudsprogrammeur weet misschien niet dat het op 2 plaatsen moet hierdoor krijg je een hoop errors als hij iets aanpast.

Ik ben het met je eens dat het niet de beste oplossing is om Meubel al die functionaliteit te geven. Maar het zorgt er wel voor de dat methode print onafhankelijk is en dat je die nooit meer hoeft te wijzigen.

Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Misschien een wat meer realistisch voorbeeld; stel je hebt een spelletje met daarin game objecten. Sommige kunnen getekend worden op het scherm, andere niet. Dus je hebt als voorbeeld:

class GameEntity
class Monster extends GameEntity implements Drawable

GameEntity bevat code om entiteiten persistent te maken e.d.

Oftewel, een 'monster' is een GameEntity (moet persistent zijn e.d.), maar implementeert ook Drawable omdat hij op het scherm getekend kan worden.

@jwgoverg: meen je werkelijk waar dat je in plaats van een Drawable interface een draw() method in GameEntity zou definieren hoewel niet alle game entities op het scherm getekend moeten worden?
bronce schreef op woensdag 06 april 2011 @ 13:05:
Ja maar de afhankelijkheid die creëert door de verantwoordelijkheid bij de collectie te leggen is ook niet het beste ontwerp. Stel ik voeg een klasse Stoel die die wil ik sitable maken dan moet ik een Stoel maken die Sitable implementeert en sit() overriden EN je moet in je collectie een check doen naar instanceof Sitable.
Nou zijn er nog wel meer eigenschappen te bedenken dan Sitable en Openable het probleem hier is dus die afhankelijkheid als je iets wilt toevoegen of verwijderen moet dit op twee plaatsen hierdoor wordt je programma onderhoudsonvriendelijk en een onderhoudsprogrammeur weet misschien niet dat het op 2 plaatsen moet hierdoor krijg je een hoop errors als hij iets aanpast.

Ik ben het met je eens dat het niet de beste oplossing is om Meubel al die functionaliteit te geven. Maar het zorgt er wel voor de dat methode print onafhankelijk is en dat je die nooit meer hoeft te wijzigen.
Als je "sit()" in "Meubel" stopt moet je collection net zo goed een "CannnotSitException" af gaan vangen omdat je het aanroept op een meubel (kast) waarop je niet kunt zitten toch? Wat is volgens jou efficienter; vooraf kijken of een object wel een interface implementeert, of gewoon maar aanroepen die hap en kijken wat er gebeurt?

[ Voor 50% gewijzigd door Hydra op 06-04-2011 13:14 ]

https://niels.nu


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

bronce schreef op woensdag 06 april 2011 @ 13:05:
Ja maar de afhankelijkheid die creëert door de verantwoordelijkheid bij de collectie te leggen is ook niet het beste ontwerp. Stel ik voeg een klasse Stoel die die wil ik sitable maken dan moet ik een Stoel maken die Sitable implementeert en sit() overriden EN je moet in je collectie een check doen naar instanceof Sitable.
Nou zijn er nog wel meer eigenschappen te bedenken dan Sitable en Openable het probleem hier is dus die afhankelijkheid als je iets wilt toevoegen of verwijderen moet dit op twee plaatsen hierdoor wordt je programma onderhoudsonvriendelijk en een onderhoudsprogrammeur weet misschien niet dat het op 2 plaatsen moet hierdoor krijg je een hoop errors als hij iets aanpast.
Je moet linksom of rechtsom ergens toegeven. En dan is het een stuk netter om geen functionaliteit aan een klasse te hangen die niets doet. Dat nodigt alleen maar uit tot bugs.

Verder is er nog een verschil tussen jouw voorstel en dat van Cheatah: dat van Cheatah weet dat hij met Kasten aan het schuiven is. Jouw code weet dat niet. Voor hetzelfde geld voer je vervolgens omdat je dat niet weet een Stoel aan een functie die alleen overweg kan met objecten die je kan openen. Dan heb je een probleem: in het beste geval klopt je code, en in het slechtste geval werkt je applicatie wel maar doet hij gekke dingen. En vooral dat laatste is heel lastig terug te vinden. ;)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
Eén van de regels in OO design: abstract what is common.

Is 'Open' common voor alle meubels ? Maw, kan je alle meubels openen ? Neen. Dus, Open() hoort niet thuis in meubel.

Zeg nu zelf, wat is cleaner / logischer:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public abstract class Meubel
{
     public abstract void Open();
}

public class Kast : Meubel
{
     public override void Open()
     {
           Console.WriteLine ("kast geopend.");
     }
}

public class Stoel : Meubel
{
      public override void Open()
      {
            throw new NotSupportedException ("Je kan een stoel niet openen.");
      }
}

public class Program
{
     public static void Main()
     {
           // ...
           foreach( Meubel m in meubels )
           {
                 try
                 {
                      m.Open();
                 }
                 catch( NotSupportedException ex)
                 {
                       Trace.WriteLine (ex.Message);
                 }
           }
     }
}


of
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Meubel
{
       // ...
}

public interface IOpenable
{
       void Open();
}

public class Stoel : Meubel {}

public class Kast : Meubel, IOpenable
{
        public void Open()
        {
             Console.WriteLine ("kast geopend.");
        }
}

public class Program
{
        public static void Main()
        {
            // geef me een collectie van alle meubels die ik kan openen.
             var items = meubels.OfType <IOpenable>().ToList();
             
             foreach( i in items )
             {
                     i.Open();
             }
        }
}

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Hydra schreef op woensdag 06 april 2011 @ 13:10:
Als je "sit()" in "Meubel" stopt moet je collection net zo goed een "CannnotSitException" af gaan vangen omdat je het aanroept op een meubel (kast) waarop je niet kunt zitten toch?
Wij zitten thuis altijd op kasten :+

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!

  • Vinnienerd
  • Registratie: Juli 2000
  • Laatst online: 22:14
Conclusie: in dit geval is instanceof gelegitimeerd. Klaar. :P

Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 08-09 11:33
Het is misschien lichtelijk offtopic, maar toevallig zag ik laatst een leuke manier om het te doen in C# (wie weet kan het ook in JAVA) dmv het dynamic keyword. Het voordeel is dat je altijd de best matchende methode uitvoert, het nadeel is dat je de Open functie buiten de class moet halen.

C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void OpenSpecialization(Kast k);
void OpenSpecialization(Meubel m);
void OpenSpecialization(Tafel t);

  void Open(Meubel m) 
    { 
        OpenSpecialization(m as dynamic); 
    }

Kast k;
Tafel t;
Lamp l;
Open(k);  //voert over load met Kast class uit
Open(t); //voert overload met Tafel class uit.
Open(l); //Voert overload met Meubel uit aangezien er geen specifiekere case is.


Meer info: http://blogs.msdn.com/b/s...spatch-via-c-dynamic.aspx

Edit: zo hoef je dus geen instanceof switch te gebruiken, de methode voor meubel kan bijvoorbeeld een stub zijn voor als er niets gebeurt. Verder werkt deze techniek omdat het keyword dynamic ervoor zorgt dat de overload pas at runtime geresolved wordt ipv at compile time, en at runtime weet de IL/JVM natuurlijk wel wat voor exact type een object heeft.

[ Voor 17% gewijzigd door roy-t op 06-04-2011 13:36 ]

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
@roy-t: maar je houdt nog steeds het probleem dat je de call alleen mag doen als er een implementatie voor Open is, dus je zult alsnog eerst moeten controleren of IOpenable wel geïmplementeerd is. In dit geval schiet je er dus niks mee op.

Of je moet een dummy implementatie maken die niks doet. Ik het geval van je tafel is het namelijk helemaal niet logisch om er Open op aan te moeten roepen ( Behalve als er natuurlijk weer een la in zit o.i.d. ;) ).

[ Voor 31% gewijzigd door Woy op 06-04-2011 13:39 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 08-09 11:33
Ja e nee, je fallback (de overload met meubel) zal gewoon niets doen, terwijl specifieke types die wel geopend willen worden een overload presenteren, dit maakt wel je publieke interface groter, en dat kan natuurlijk erg onwenselijk zijn. Een andere structurering van data types zou daar misschien bij helpen.

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
Woy schreef op woensdag 06 april 2011 @ 13:36:
@roy-t: maar je houdt nog steeds het probleem dat je de call alleen mag doen als er een implementatie voor Open is, dus je zult alsnog eerst moeten controleren of IOpenable wel geïmplementeerd is. In dit geval schiet je er dus niks mee op.
Idd, Je kan wel syntax schrijven waarbij je een Open method aanroept op gelijk welk object, maar als dat object geen Open method heeft, krijg je een RTE.

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
roy-t schreef op woensdag 06 april 2011 @ 13:39:
Ja e nee, je fallback (de overload met meubel) zal gewoon niets doen, terwijl specifieke types die wel geopend willen worden een overload presenteren, dit maakt wel je publieke interface groter, en dat kan natuurlijk erg onwenselijk zijn. Een andere structurering van data types zou daar misschien bij helpen.
Maar je blijft dan een (dummy) implementatie maken voor Meubel (of meteen object), die nergens op slaat. In dit geval is het gebruik van instanceof IMHO nog steeds een stuk netter.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

roy-t schreef op woensdag 06 april 2011 @ 13:39:
Ja e nee, je fallback (de overload met meubel) zal gewoon niets doen, terwijl specifieke types die wel geopend willen worden een overload presenteren, dit maakt wel je publieke interface groter, en dat kan natuurlijk erg onwenselijk zijn. Een andere structurering van data types zou daar misschien bij helpen.
Je doet dan precies hetzelfde als wat jwgoverg doet: functionaliteit aanbieden die niets doet. Vind ik niet mooi, al is het met deze code IMO wel mooier/overzichtelijker dan de code van jwgoverg. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
NMe schreef op woensdag 06 april 2011 @ 13:48:
[...]

Je doet dan precies hetzelfde als wat jwgoverg doet: functionaliteit aanbieden die niets doet. Vind ik niet mooi, al is het met deze code IMO wel mooier/overzichtelijker dan de code van jwgoverg. :)
Niet helemaal; dat dynamic keyword zorgt voor duck-typing. Je gaat ervan uit dat het dynamic object een method open heeft, en heeft deze dat niet, dan krijg je een RTE voor de kiezen.
Eigenlijk zou je dat dus enkel mogen aanroepen als je weet dat het object een open method heeft. (Vooral handig bij COM interop binnen .NET).

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Jeanpaul145
  • Registratie: Juli 2007
  • Laatst online: 15-07 14:52
Hydra schreef op woensdag 06 april 2011 @ 12:05:
[...]


Inderdaad. Ik gebruik het zelf bijna nooit omdat ik het meestal niet nodig heb. In heel enkele gevallen heb je een collectie objecten die verder niet gerelateerd zijn waarvan je moet gaan uitvogelen van welk type ze zijn. Mag je mij gaan uitleggen hoe je dat kan doen zonder instanceof, dat visitor-pattern hierboven werkt dan niet.
Ok, misschien moet ik mezelf wat verduidelijken:

Ten eerste heb ik nooit geclaimd dat instanceof per definitie evil is, alleen dat ik het lelijk vind voor objectoriëntatie waar behoorlijke abstractie beter op z'n plek is. Dogma's moeten ten alle tijden vermeden worden IMO (en ja ik snap de ironie van deze zin dus het heeft geen zin daarop in te gaan ;) ).
Je hebt overigens wel gelijk, als je de situatie tegenkomt waarin je stuk voor stuk moet gaan uitvogelen welk runtime-type elk object in een collectie heeft dan kan je niet om de instanceof heen. Maar in mijn ervaring is dat vaak al een symptoom van slecht ontwerp, en dan steek ik liever mn tijd in het uit elkaar trekken van zo'n collection in een aantal collection objects die een type hebben die wat lager in die hierarchie zit, dan doorgaan met die slechte code.

Ten tweede is er nooit een "one size fits all" oplossing, de enige 100% generieke uitspraak die er gedaan kan worden is iets van de strekking "beslis a.d.h.v. de situatie welk patroon het meest geschikt is". Het probleem met deze uitspraak is natuurlijk dat er niets over specifieke situaties wordt gezegd.

Zelf zou ik t, als ik van scratch zou klussen, denk ik als volgt oplossen in productiecode (voor een supersimpel voorbeeld maakt het eigenlijk niet uit maar dit vind ik wel mooie code):
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public abstract class FurnitureItem {
    private final String id;
    
    public FurnitureItem(String id) {
        super();
        this.id = id;
    }
    
    public String getId() {
        return id;
    }

    public abstract void place();
}

Java:
1
2
3
4
5
6
7
8
public abstract class OpenableFurnitureItem extends FurnitureItem {
    
    public OpenableFurnitureItem(String id) {
        super(id);
    }
    
    protected abstract void onOpen();
}

Java:
1
2
3
4
5
6
7
8
public abstract class Seat extends FurnitureItem {

    public Seat(String id) {
        super(id);
    }
    
    protected abstract void onSitOn();
}

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Closet extends OpenableFurnitureItem {
    
    public Closet(String id) {
        super(id);
    }

    @Override
    protected void onOpen() {
        System.out.println("Opened " + getId());
    }

    @Override
    public void place() {
        System.out.println("Placed " + getId() + " somehere");
        // Some Closet-specific stuff
    }
}

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Couch extends Seat {
    
    public Couch(String id) {
        super(id);
    }

    @Override
    protected void onSitOn() {
        System.out.println(getId() + " is being sat on.");
    }

    @Override
    public void place() {
        System.out.println("Placed " + getId() + " somehere");
        // Some Couch-specific stuff
    }
}

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class User {
    
    private String name;

    public User(String name) {
        super();
        this.name = name;
    }
    
    public String getName() {
        return name;
    }
    
    public void sitOn(Seat seat) {
        System.out.println(this.name + " takes a seat on " + seat.getId());
        seat.onSitOn();
    }
    
    public void open(OpenableFurnitureItem ofi) {
        System.out.println(this.name + " opens " + ofi.getId());
        ofi.onOpen();
    }
}

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Main {

    private static final int NUM_ITEMS = 3;
    
    public static void main(String[] args) {
        User user = new User("Jack Daniels");
        
        OpenableFurnitureItem[] openables = new OpenableFurnitureItem[NUM_ITEMS];
        Seat[] seats = new Seat[NUM_ITEMS];
        
        for (int i = 0; i < NUM_ITEMS; i++) {
            openables[i] = new Closet("Closet " + i);
            seats[i] = new Couch("Couch " + i);
        }
        
        for (int i = 0; i < NUM_ITEMS; i++) {
            user.sitOn(seats[i]);
            seats[i].place();
            user.open(openables[i]);
            openables[i].place();
            System.out.println(); // for readability purposes
        }
    }
}


Output:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Jack Daniels takes a seat on Couch 0
Couch 0 is being sat on.
Placed Couch 0 somehere
Jack Daniels opens Closet 0
Opened Closet 0
Placed Closet 0 somehere

Jack Daniels takes a seat on Couch 1
Couch 1 is being sat on.
Placed Couch 1 somehere
Jack Daniels opens Closet 1
Opened Closet 1
Placed Closet 1 somehere

Jack Daniels takes a seat on Couch 2
Couch 2 is being sat on.
Placed Couch 2 somehere
Jack Daniels opens Closet 2
Opened Closet 2
Placed Closet 2 somehere


Let op de 2 arrays in de main-methode: die maken het grootste verschil van alles, omdat ze ervoor zorgen dat ik de arrays van het type kan declareren die de operaties kunnen uitvoeren (OpenableFurnitureItem die geopend kan worden en Seat waar op gezeten kan worden) die je wil hebben.

:j


Acties:
  • 0 Henk 'm!

  • Big Joe
  • Registratie: Maart 2004
  • Laatst online: 02-08 15:22
Ja java blijft lastig, gelukkig is het in C# allemaal een stuk beter geregeld en los je dit soort problemen zo op.


C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
    public class Meubel
    {
        public void plaats()
        {
            Console.WriteLine("Meubel geplaatst");
        }
    }

    class Kast : Meubel
    {
        public void open()
        {
            Console.WriteLine("Kast geopend");
        }
    }

    class Bank : Meubel
    {
    }

    static class MeubelCheckerHelper
    {
        public static String openableMeubels = "meubeltestcase.Kast;meubeltestcase.Kledingkast";
        public static bool isOpenableMeubel(Meubel meubel)
        {
            foreach (String meubelclass in openableMeubels.Split(';'))
            {
                if (meubel.GetType().ToString() == meubelclass)
                {
                    return true;
                }
            }
            return false;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Kast meubel1 = new Kast();
            Bank meubel2 = new Bank();
            List<Meubel> meubels = new List<Meubel>();
            meubels.Add(meubel1);
            meubels.Add(meubel2);
            foreach (Meubel m in meubels)
            {
                if (MeubelCheckerHelper.isOpenableMeubel(m))
                {
                    foreach (String meubelclass in MeubelCheckerHelper.openableMeubels.Split(';'))
                    {
                        if (meubelclass == "meubeltestcase.Kast")
                        {
                            Kast kast = (Kast)m;
                            kast.open();
                        }
                    }
                }
            }
            Console.ReadKey();
        }
    }


En mochten er dan teveel classes openable zijn kan je het beste even de classnames in een database zetten ipv alsstring.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ah ja, ga strings zitten comparen. Mooie oplossing om maar geen instanceof te gebruiken 8)7

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!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 08-09 11:33
imho is dat de lelijkste oplossing hier tot nu toe, en is dit (zelfs door een Java leek als ik) direct toe te passen in Java.

Edit: wat nog wel een leuke optie is (misschien) om instanceof wat te verbergen is om in de foreach een iterator op te vragen die uit een andere iterator (Vector<>/ array ofzo) alle objecten die Interface X implementeren terug geeft. In C# zou je dit met Linq kunnen doen (wat stiekem nog een abstractie is) maar in Java zou je dit altijd nog met een gewoon een eigen class die iterator extend en een ifje kunnen doen.

[ Voor 68% gewijzigd door roy-t op 06-04-2011 14:50 ]

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • Amras
  • Registratie: Januari 2003
  • Laatst online: 11-09 19:11
Laten we hopen dat de TS de juiste posts leest, want het wordt er niet beter op. In een string definieren welke classes nu wel en niet openable zijn, is niet echt fraai. Daarbij is het in de database steken van dit soort informatie al helemaal onzin: alsof je dynamisch objecten gaat uitbreiden met open functionaliteit, terwijl je daarna in code nog een if-statement moet toevoegen en downcasten voordat je daadwerkelijk de open-methode kunt aanroepen.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

.oisyn schreef op woensdag 06 april 2011 @ 14:42:
Ah ja, ga strings zitten comparen. Mooie oplossing om maar geen instanceof te gebruiken 8)7
Doet me denken aan de eeuwige eval == evil-discussie.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Big Joe
  • Registratie: Maart 2004
  • Laatst online: 02-08 15:22
Het gaat erom dat het werkt, en ik durf te wedden dat de Ikea het ook op deze manier zou doen als ze programmeurs met ervaring hebben.

En de methode MeubelCheckerHelper is het toppunt van OO programmeren die makkelijk uit te bereiden is met bijvoorbeeld isSittableMeubel. Je zou van MeubelCheckerHelper ook nog een superclass kunnen maken en dan voor elke soort functie een subclass maken. Bijvoorbeeld MeubelSittableCheckerHelper die dan erft van MeubelCheckerHelper.

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
Big Joe schreef op woensdag 06 april 2011 @ 14:56:
Het gaat erom dat het werkt, en ik durf te wedden dat de Ikea het ook op deze manier zou doen als ze programmeurs met ervaring hebben.
Ja, en dan gaan we even gaan refactoren en die class een andere naam geven, of we verhuizen ze naar een andere namespace .... En dan werkt het plots niet meer.
En de methode MeubelCheckerHelper is het toppunt van OO programmeren die makkelijk uit te bereiden is met bijvoorbeeld isSittableMeubel. Je zou van MeubelCheckerHelper ook nog een superclass kunnen maken en dan voor elke soort functie een subclass maken. Bijvoorbeeld MeubelSittableCheckerHelper die dan erft van MeubelCheckerHelper.
8)7 8)7

[ Voor 3% gewijzigd door whoami op 06-04-2011 14:59 ]

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Amras
  • Registratie: Januari 2003
  • Laatst online: 11-09 19:11
Big Joe schreef op woensdag 06 april 2011 @ 14:56:
Het gaat erom dat het werkt, en ik durf te wedden dat de Ikea het ook op deze manier zou doen als ze programmeurs met ervaring hebben.
Ervaring zegt niets, je kunt ook jaren ervaring hebben in het schrijven van slechte code.
En de methode MeubelCheckerHelper is het toppunt van OO programmeren die makkelijk uit te bereiden is met bijvoorbeeld isSittableMeubel. Je zou van MeubelCheckerHelper ook nog een superclass kunnen maken en dan voor elke soort functie een subclass maken. Bijvoorbeeld MeubelSittableCheckerHelper die dan erft van MeubelCheckerHelper.
Iedere class die eindigt op Helper is een toppunt van slecht OO programmeren. Wat doet een helper?

Acties:
  • 0 Henk 'm!

  • CodeCaster
  • Registratie: Juni 2003
  • Niet online

CodeCaster

Can I get uhm...

Big Joe schreef op woensdag 06 april 2011 @ 14:56:
Het gaat erom dat het werkt, en ik durf te wedden dat de Ikea het ook op deze manier zou doen als ze programmeurs met ervaring hebben.
Het is een ranzige workaround die nog steeds neerkomt op het controleren van het type. In plaats van netjes het resultaat van GetType te gebruiken en te kijken of de instantie een Kast is (*kuch* instanceOf) ga jij raar lopen doen met strings (wat als de namespace of erger nog de naam van de klasse verandert?).
En de methode MeubelCheckerHelper is het toppunt van OO programmeren die makkelijk uit te bereiden is met bijvoorbeeld isSittableMeubel. Je zou van MeubelCheckerHelper ook nog een superclass kunnen maken en dan voor elke soort functie een subclass maken. Bijvoorbeeld MeubelSittableCheckerHelper die dan erft van MeubelCheckerHelper.
Ja, want als je een ranzige methode in een even ranzige klasse stopt is het ineens het toppunt van OO?

https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Big Joe schreef op woensdag 06 april 2011 @ 14:56:
Het gaat erom dat het werkt, en ik durf te wedden dat de Ikea het ook op deze manier zou doen als ze programmeurs met ervaring hebben.
It works! Ship it!

Sorry, maar dit is geen goeie instelling en dat weet je zelf ongetwijfeld ook. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • BSTNjitRam
  • Registratie: November 2004
  • Laatst online: 20:18
Big Joe schreef op woensdag 06 april 2011 @ 14:56:

En de methode MeubelCheckerHelper is...
Dit zegt wel genoeg toch?

Wishlist Backpack Survivors op Steam !


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ook leuk hoe die code niet werkt met subclasses van Kast.

Áls je het op een dergelijke manier wilt doen, doe het dan niet met een te splitten string met types, maar gewoon met een array van types (jeweetwel, System.Type), zodat je gewoon aan dat type object kunt vragen of een object daar een instantie van is.

I vote worst code ever. Wie maakt er een DailyWTF post van?

@Big Joe: schoenmaker, blijf bij je leest

[ Voor 85% gewijzigd door .oisyn op 06-04-2011 15:08 ]

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!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

.oisyn schreef op woensdag 06 april 2011 @ 15:04:
Ook leuk hoe die code niet werkt met subclasses van Kast.
Dan maak je Kast toch gewoon final?!?!

:+

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

Verwijderd

.oisyn schreef op woensdag 06 april 2011 @ 15:04:

I vote worst code ever. Wie maakt er een DailyWTF post van?
Bij deze heb ik de tag aangevraagd... :X

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Big Joe schreef op woensdag 06 april 2011 @ 14:38:
C#:
1
2
3
4
if (meubel.GetType().ToString() == meubelclass)
{
    return true;
}
:X 8)7

Doe 't dan goed:

C#:
1
return meubel.GetType().ToString().Trim().ToLowerInvariant().Equals("meubeltestcase.kast", StringComparison.InvariantCultureIgnoreCase);

:X :+ 8)7

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

meubel.GetType().ToString() == "string" is natuurlijk veel mooier dan meubel instanceof string, duh! :P

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 01:31

MueR

Admin Tweakers Discord

is niet lief

Verwijderd schreef op woensdag 06 april 2011 @ 15:08:
[...]

Bij deze heb ik de tag aangevraagd... :X
To approve, or not to approve, that is the question..

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 03:22
offtopic:
To approve or not to approve == true, dûh. Zijn we hier nu programmeurs of niet?

Acties:
  • 0 Henk 'm!

  • BSTNjitRam
  • Registratie: November 2004
  • Laatst online: 20:18
Soultaker schreef op woensdag 06 april 2011 @ 15:28:
offtopic:
To approve or not to approve == true, dûh. Zijn we hier nu programmeurs of niet?
offtopic:
En hoe weet jij zo zeker dat het niet FileNotFound is?

Wishlist Backpack Survivors op Steam !


Acties:
  • 0 Henk 'm!

  • ReenL
  • Registratie: Augustus 2010
  • Laatst online: 14-09-2022
Wel geweldig dat we allemaal een hele theoretische case aan het oplossen zijn.

Het drawable voorbeeld vond ik mooi (omdat het praktisch is). Daarbij heet de interface namelijk een collectie aan drawables, de gamecontroller een collectie van gameentities en de ai een collectie van monsters.

De interface, gamecontroller en de ai hoeven deze types niet meer te checken. Ze accepteren namelijk geen instances van andere typen.

Wanneer is de "Kast.open" en "Stoel.zit" realistisch? Als je een grote schuur hebt met honderden meubels en je gaat kijken of ze allemaal nog werken. Dan is het best logisch dat als je voor een meubel staat, dat je even controleert watvoor meubel het is en afhankelijk daarvan even kijkt of het er goed uit ziet.

Dan weet je gelijk waarom je Openable en Sitable moet implementeren. Anders moet je voor "Stoel" en "Bank" opnieuw de testmethod aanmaken.

Bovenstaand lijkt me in de programmeer wereld niet vaak voorkomen, behalve als je dus voorbeeld code aan het schrijven bent.
offtopic:
En hoe weet jij zo zeker dat het niet FileNotExists is?
(to apporove or not to approve) instanceof FileNotExist == false

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

ReenL schreef op woensdag 06 april 2011 @ 15:32:
Wanneer is de "Kast.open" en "Stoel.zit" realistisch? Als je een grote schuur hebt met honderden meubels en je gaat kijken of ze allemaal nog werken. Dan is het best logisch dat als je voor een meubel staat, dat je even controleert watvoor meubel het is en afhankelijk daarvan even kijkt of het er goed uit ziet.
controleerWerking() zou dan best wel weer een methode kunnen zijn op Meubel, die afhankelijk van de meubel verschillend geïmplementeerd is.
ReenL schreef op woensdag 06 april 2011 @ 15:32:
Het drawable voorbeeld vond ik mooi (omdat het praktisch is). Daarbij heet de interface namelijk een collectie aan drawables, de gamecontroller een collectie van gameentities en de ai een collectie van monsters.
Hoeft niet per se. Kijk bijvoorbeeld eens naar Java3D, daar wordt alles gewoon in een grote boomstructuur gemikt.

Niet dat ik dat nou echt een fantastische API vind overigens, maar het is niet zonder meer zo dat je collecties altijd volledig uitgespecificeerd zijn.

[ Voor 34% gewijzigd door .oisyn op 06-04-2011 15:41 ]

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!

Verwijderd

ReenL schreef op woensdag 06 april 2011 @ 15:32:
Wel geweldig dat we allemaal een hele theoretische case aan het oplossen zijn.

Het drawable voorbeeld vond ik mooi (omdat het praktisch is). Daarbij heet de interface namelijk een collectie aan drawables, de gamecontroller een collectie van gameentities en de ai een collectie van monsters.
Vanuit performance-perspectief zal dat ongetwijfeld een goed idee zijn :)
De interface, gamecontroller en de ai hoeven deze types niet meer te checken. Ze accepteren namelijk geen instances van andere typen.
Maar hoe krijg je een object in de juiste collecties? ;)

Acties:
  • 0 Henk 'm!

  • Vinnienerd
  • Registratie: Juli 2000
  • Laatst online: 22:14
IMHO is instanceof iets heel anders dan eval of het comparen van .toString()s. Bij instanceof ben je zelf al dingen aan het afvangen, bij eval of .toString zit je met een bepaalde mate van onvoorspelbaarheid. instanceof is gewoon een operator waarmee je iets vergelijkt, je verneukt je VM er niet mee oid. Mensen die gaan roepen dat instanceof ranzig is zijn bezig met "overcorrect programmeren". Abstract denken is mooi, maar soms moet je gewoon specifiek zijn :+

Acties:
  • 0 Henk 'm!

Verwijderd

Vinnienerd schreef op woensdag 06 april 2011 @ 16:46:
Mensen die gaan roepen dat instanceof ranzig is zijn bezig met "overcorrect programmeren". Abstract denken is mooi, maar soms moet je gewoon specifiek zijn :+
Dat is de reden waarom mensen die roepen dat je geen goto mag gebruiken en dat eval altijd vies is, niet al te serieus genomen moeten worden.

Ik denk dat de consensus is dat onervaren programmeurs er geen gebruik van zouden moeten maken, maar dat het gebruik in sommige gevallen wel is te verantwoorden. Om te bepalen of dat zo is, moet je uiteraard het nodige inzicht en de nodige ervaring hebben.

Maar dan nog vind ik instanceof van compleet ander kaliber dan goto en eval.

[ Voor 6% gewijzigd door Verwijderd op 06-04-2011 16:57 ]


Acties:
  • 0 Henk 'm!

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Verwijderd schreef op woensdag 06 april 2011 @ 16:56:
Maar dan nog vind ik instanceof van compleet ander kaliber dan goto en eval.
Er zijn allerlei code constructs die je bij voorkeur niet zou moeten gebruiken. Maar soms wordt je inderdaad voor de keuze gesteld om toch maar de construct te gebruiken of er omheen te werken.

Als je met nette en duidelijke code kunt vermijden dat je de constructs gebruikt of de reden dat je het uberhaupt checkt kunt voorkomen... graag. Maar als je om een enorme (maar wel nette) hoeveelheid code moet produceren enkel om hetzelfde probleem op te lossen? Sja, dan moet je je alsnog weer achter je oren gaan krabben. Misschien was de instanceof (of goto, eval, meerdere returns, etc) dan toch een beter idee.
Hydra schreef op woensdag 06 april 2011 @ 13:10:
Als je "sit()" in "Meubel" stopt moet je collection net zo goed een "CannnotSitException" af gaan vangen omdat je het aanroept op een meubel (kast) waarop je niet kunt zitten toch? Wat is volgens jou efficienter; vooraf kijken of een object wel een interface implementeert, of gewoon maar aanroepen die hap en kijken wat er gebeurt?
Dit is een gevaarlijke vraag :P Als geen (of slechts enkele) van de objecten een exception opgooien (dus alles Sitable is) is het namelijk goed mogelijk dat de variant met exception-check efficienter is dan de instanceof-variant.

Desalniettemin zou ik in dit geval ook de instanceof-variant kiezen en hooguit bij wijze van micro-optimalisatie vol in het kritieke pad onderaan de lijst overwegen om te kijken of er een alternatieve - nog efficientere - methode is om het te doen :P Hoewel dat dan hopelijk een variant zou zijn waarbij ik de hele controle voor Sitable kan overslaan door eerder al zeker te stellen dat het een Sitable is of door de JVM dat voor me te laten regelen.

Acties:
  • 0 Henk 'm!

  • Vinnienerd
  • Registratie: Juli 2000
  • Laatst online: 22:14
Verwijderd schreef op woensdag 06 april 2011 @ 16:56:
[...]
Maar dan nog vind ik instanceof van compleet ander kaliber dan goto en eval.
Dat schrijf ik toch ook? Of heb je het nu niet tegen mij?

Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
.oisyn schreef op woensdag 06 april 2011 @ 15:04:
Ook leuk hoe die code niet werkt met subclasses van Kast.
I think we have a winner. Dat is wel de ultieme reden dat het gewoon helemaal compleet fout is.

class ServiesKast extends Kast. Dat IS gewoon een kast, maar volgens het voorbeeld niet. Te slecht gewoon.
ACM schreef op woensdag 06 april 2011 @ 17:26:
Dit is een gevaarlijke vraag :P Als geen (of slechts enkele) van de objecten een exception opgooien (dus alles Sitable is) is het namelijk goed mogelijk dat de variant met exception-check efficienter is dan de instanceof-variant.
Ik bedoel efficienter vanuit een programmeerstandpunt, niet performance. Dat zou wel een vorm van premature optimization zijn :)

https://niels.nu


Acties:
  • 0 Henk 'm!

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
Een aantal mensen zijn behoorlijk afgedwaald van de vraag en in plaats daarvan erg bezig met het verzinnen van alternatieven voor het gepresenteerde voorbeeld.

Zoals .oisyn al zei: het probleem zit waarschijnlijk helemaal niet in Meubel/Kast/Openable, maar in de collectie/array van het type Meubel en het beoogde gebruik daarvan.

Het feit dat je instanceof nodig hebt om bepaalde instanties in die lijst eruit te filteren, is eerder een indicatie van een probleem met die lijst, dan van een probleem met de types van die instanties.

Als je graag alle Kasten wilt openen, moet je een collectie van Kasten maken, geen collectie van Meubels.

[ Voor 4% gewijzigd door Herko_ter_Horst op 06-04-2011 19:44 ]

"Any sufficiently advanced technology is indistinguishable from magic."


Acties:
  • 0 Henk 'm!

Verwijderd

Vinnienerd schreef op woensdag 06 april 2011 @ 17:28:

Dat schrijf ik toch ook? Of heb je het nu niet tegen mij?
Ik had het niet zozeer tegen jou, ik was aan het voortborduren op de gedachte :)

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Herko_ter_Horst schreef op woensdag 06 april 2011 @ 18:52:
Als je graag alle Kasten wilt openen, moet je een collectie van Kasten maken, geen collectie van Meubels.
Maar bij het toevoegen weet je nou eenmaal niet altijd wat het is, en dus zul je op dat punt moeten controleren wat het is ( met instanceof bijvoorbeeld ). Als er een duidelijk onderscheid te maken is bij het toevoegen, moet je dat zeker doen. Maar vroeger of later kom je vanzelf een situatie tegen waar je eigenlijk een te generieke collectie gebruikt.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
Woy schreef op woensdag 06 april 2011 @ 19:44:
[...]

Maar bij het toevoegen weet je nou eenmaal niet altijd wat het is, en dus zul je op dat punt moeten controleren wat het is ( met instanceof bijvoorbeeld ). Als er een duidelijk onderscheid te maken is bij het toevoegen, moet je dat zeker doen. Maar vroeger of later kom je vanzelf een situatie tegen waar je eigenlijk een te generieke collectie gebruikt.
De vraag is of in zo'n geval de verantwoordelijkheden goed liggen. Moet de class die de generieke collectie van Meubels beheert, wel dezelfde class zijn die Kasten open doet?

"Any sufficiently advanced technology is indistinguishable from magic."


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Herko_ter_Horst schreef op woensdag 06 april 2011 @ 19:51:
[...]

De vraag is of in zo'n geval de verantwoordelijkheden goed liggen. Moet de class die de generieke collectie van Meubels beheert, wel dezelfde class zijn die Kasten open doet?
Hoe zie je het dan voor je? Natuurlijk is een Kamer ( o.i.d. ) niet de aangewezen class om meubels te openen, maar als er bijvoorbeeld een Persoon is die dat zou doen, dan moet die alsnog uit de kamer alle IOpenable objecten verkrijgen, en dan heb je daar alsnog iets van instanceof voor gebruiken.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Big Joe
  • Registratie: Maart 2004
  • Laatst online: 02-08 15:22
whoami schreef op woensdag 06 april 2011 @ 14:58:
[...]
Ja, en dan gaan we even gaan refactoren en die class een andere naam geven, of we verhuizen ze naar een andere namespace .... En dan werkt het plots niet meer.

[...]
8)7 8)7
Bij mij op mijn werk gebruiken we het waterval model en is dit niet van toepassingen. Klassendiagrammen en ontwerpen worden van tevoren opgezet met UML, zodat namen vaststaan en nooit zullen veranderen. Het is een kleine opoffering die je moet maken als je echt om de performance van je applicatie geeft.
Iedere class die eindigt op Helper is een toppunt van slecht OO programmeren. Wat doet een helper?
Een helper is in dit geval een soort controller die de applicatie helpt om te bepalen welke meubelen een kast zijn. Dit is een veelgebruikte best-practice om de applicatie-logica, het data model en de presentatie-laag van elkaar te scheiden.
Het is een ranzige workaround die nog steeds neerkomt op het controleren van het type. In plaats van netjes het resultaat van GetType te gebruiken en te kijken of de instantie een Kast is (*kuch* instanceOf) ga jij raar lopen doen met strings (wat als de namespace of erger nog de naam van de klasse verandert?).
Zoals ik al eerder vertelde hoeft de naam van een namespace of klasse niet te veranderen als je van tevoren een goed ontwerp maakt. Mijn methode is een goede manier om op een snelle en efficiente manier te controleren welke classes de methode open() hebben.

Verder vind ik het beneden peil dat jullie mijn code op zo'n negatieve manier afkraken. Ik zit al 15 jaar in het vak en heb nog nooit negatieve feedback gehad op mijn code!

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Big Joe schreef op woensdag 06 april 2011 @ 20:12:
[...]
Het is een kleine opoffering die je moet maken als je echt om de performance van je applicatie geeft.
En je denkt serieus dat een string vergelijking beter performt dan een simpele type comparison?
Zoals ik al eerder vertelde hoeft de naam van een namespace of klasse niet te veranderen als je van tevoren een goed ontwerp maakt. Mijn methode is een goede manier om op een snelle en efficiente manier te controleren welke classes de methode open() hebben.
Ten eerste is het zeker geen snelle efficiënte manier, en ten tweede is het ook erg lastig te onderhouden. Ook al maak je nog zo'n goed ontwerp van te voren, in de toekomst zullen er altijd wijzigingen of toevoegingen aan gedaan worden. Met deze manier van werken is het gewoon wachten totdat het mis gaat.
Verder vind ik het beneden peil dat jullie mijn code op zo'n negatieve manier afkraken. Ik zit al 15 jaar in het vak en heb nog nooit negatieve feedback gehad op mijn code!
Het is niet bedoeld om je persoonlijk aan te vallen, maar de manier van werken die jij voorstelt is echt geen voorbeeld van hoe je zou moeten werken. Je hebt totaal geen enkele vorm van compile-time safety, refactoring tools werken er niet goed op ( Het scheelt dat Resharper bijvoorbeeld ook in stings zoekt, maar die heeft daarbij alsnog te weinig informatie om het altijd goed te doen.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Kwistnix
  • Registratie: Juni 2001
  • Laatst online: 22:34
Uhm, iets zegt mij dat iemand hier nogal loopt te trollen ;)
Tenminste, dat hoop ik dan. Ik bedoel:
Klassendiagrammen en ontwerpen worden van tevoren opgezet met UML, zodat namen vaststaan en nooit zullen veranderen.
...
Zoals ik al eerder vertelde hoeft de naam van een namespace of klasse niet te veranderen als je van tevoren een goed ontwerp maakt.
Dat kan je gewoon niet serieus menen als je "al 15 jaar in het vak zit".

Acties:
  • 0 Henk 'm!

  • CodeCaster
  • Registratie: Juni 2003
  • Niet online

CodeCaster

Can I get uhm...

Big Joe schreef op woensdag 06 april 2011 @ 20:12:
[...]


Bij mij op mijn werk gebruiken we het waterval model en is dit niet van toepassingen. Klassendiagrammen en ontwerpen worden van tevoren opgezet met UML, zodat namen vaststaan en nooit zullen veranderen. Het is een kleine opoffering die je moet maken als je echt om de performance van je applicatie geeft.
Waterval en klassendiagrammen hebben nog minder dan niets met de performance van je applicatie te maken.
Een helper is in dit geval een soort controller die de applicatie helpt om te bepalen welke meubelen een kast zijn. Dit is een veelgebruikte best-practice om de applicatie-logica, het data model en de presentatie-laag van elkaar te scheiden.
Het heeft toch te maken met de data?
Zoals ik al eerder vertelde hoeft de naam van een namespace of klasse niet te veranderen als je van tevoren een goed ontwerp maakt. Mijn methode is een goede manier om op een snelle en efficiente manier te controleren welke classes de methode open() hebben.
Totdat er een nieuw meubelstuk wordt geïntroduceerd wat toevallig ook geopend moet kunnen worden. In het geval van de eerder genoemde code die gebruik maakt van een nette interface hoef je het nieuwe meubel alleen deze interface laten implementeren, en de rest van de code blijft onaangeraakt. In jouw geval moet je de naam van de klasse (die overigens door voortschrijdend inzicht wel degelijk kan veranderen) copypasten en in een string zetten.

Je lost er een niet-bestaand probleem (het om een of andere reden niet willen gebruiken van runtime typechecking) mee op.
Verder vind ik het beneden peil dat jullie mijn code op zo'n negatieve manier afkraken. Ik zit al 15 jaar in het vak en heb nog nooit negatieve feedback gehad op mijn code!
Dan laat je je code aan de verkeerde mensen zien. Ik wil mezelf niet onervaren noemen, maar zelfs ik zie dat jouw ontwerp gewoon inherent slecht is. Wat overigens natuurlijk niets zegt over de code die je in je dagelijkse kostwinning produceert. :)

https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 12-09 10:54

Janoz

Moderator Devschuur®

!litemod

Big Joe schreef op woensdag 06 april 2011 @ 20:12:
Bij mij op mijn werk gebruiken we het waterval model en is dit niet van toepassingen. Klassendiagrammen en ontwerpen worden van tevoren opgezet met UML, zodat namen vaststaan en nooit zullen veranderen. Het is een kleine opoffering die je moet maken als je echt om de performance van je applicatie geeft.
...
Een helper is in dit geval een soort controller die de applicatie helpt om te bepalen welke meubelen een kast zijn. Dit is een veelgebruikte best-practice om de applicatie-logica, het data model en de presentatie-laag van elkaar te scheiden.
...
Zoals ik al eerder vertelde hoeft de naam van een namespace of klasse niet te veranderen als je van tevoren een goed ontwerp maakt.
Joehoe, 1996 belde, ze willen hun wereldbeeld terug!
Verder vind ik het beneden peil dat jullie mijn code op zo'n negatieve manier afkraken. Ik zit al 15 jaar in het vak en heb nog nooit negatieve feedback gehad op mijn code!
Oeh, ik bied me bij deze vrijwillig aan voor het doen van een code review!

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!

  • Amras
  • Registratie: Januari 2003
  • Laatst online: 11-09 19:11
Ik ben het met bovenstaande mensen eens, je code is geen voorbeeld van hoe je dit soort problemen oplost. De eerder genoemde IOpenable interface is de way-to-go en jouw oplossing komt niet in de buurt van een alternatief.

Commentaar krijgen op je code kan vervelend zijn, maar je kunt er ook van leren. Ervaring zegt niet alles, zoals ik al eerder zei: je kunt ook ervaring hebben in het schrijven van slechte code. Nu kun je natuurlijk een prima programmeur zijn en zit je er in dit geval net naast, maar ik hoop dat je inziet waarom jouw voorgestelde oplossing hier niet klopt.

Acties:
  • 0 Henk 'm!

  • Big Joe
  • Registratie: Maart 2004
  • Laatst online: 02-08 15:22
Hydra schreef op woensdag 06 april 2011 @ 17:48:
[...]


I think we have a winner. Dat is wel de ultieme reden dat het gewoon helemaal compleet fout is.

class ServiesKast extends Kast. Dat IS gewoon een kast, maar volgens het voorbeeld niet. Te slecht gewoon.
Dit kun je oplossen door de code aan te passen naar het volgende:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
public class Meubel
    {
        public void plaats()
        {
            Console.WriteLine("Meubel geplaatst");
        }
    }

    class Kast : Meubel
    {
        public void open()
        {
            Console.WriteLine("Kast geopend");
        }
    }

    class ServiesKast : Kast
    {
        new public void open()
        {
            Kast k = new Kast();
            k.open();
        }
    }

    class Bank : Meubel
    {
    }

    static class MeubelCheckerHelper
    {
        public static String openableMeubels = "meubeltestcase.Kast;meubeltestcase.ServiesKast";
        public static bool isOpenableMeubel(Meubel meubel)
        {
            foreach (String meubelclass in openableMeubels.Split(';'))
            {
                if (meubel.GetType().ToString() == meubelclass)
                {
                    return true;
                }
            }
            return false;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Kast meubel1 = new Kast();
            ServiesKast meubel2 = new ServiesKast();
            List<Meubel> meubels = new List<Meubel>();
            meubels.Add(meubel1);
            meubels.Add(meubel2);
            foreach (Meubel m in meubels)
            {
                if (MeubelCheckerHelper.isOpenableMeubel(m))
                {
                    foreach (String meubelclass in MeubelCheckerHelper.openableMeubels.Split(';'))
                    {
                        if (meubelclass == "meubeltestcase.Kast")
                        {
                            Kast kast = (Kast)m;
                            kast.open();
                        }
                    }
                }
            }
            Console.ReadKey();
        }
    }

Acties:
  • 0 Henk 'm!

  • Amras
  • Registratie: Januari 2003
  • Laatst online: 11-09 19:11
Waarom maakt een Servieskast een nieuwe Kast en opent deze, terwijl er wordt gevraagd om de Servieskast te openen?

Acties:
  • 0 Henk 'm!

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Er zijn ook banken die open kunnen (opslagruimte onder de zitting) en meubelkisten op wieltjes waar je op kan zitten (kussen op het deksel). Hoe ga je die in een dergelijk model proberen te stoppen?

Het grote voordeel van interfaces is juist dat je nog een gedeelte van je abstractie bewaard en dat je er dus eventueel meerdere tegelijk kan invoeren. Dan heb je iets als "ZitbareMeubelKist implements Seatable, Openable, Rollable" wat je dan vervolgens kan testen op instanceof Seatable, danwel Openable of Rollable... Hoe meer van dat soort "labels" aan een object te hangen zijn, hoe lastiger het wordt om een starre hierarchie aan te houden.

Jouw string-check is enkel een vervanger voor de instanceof op een te diep niveau en voegt verder niet zoveel toe. Nouja, hoofdpijn zodra je dingen wilt refactoren. Want if(m instanceof Openable) vangt ook gelijk die te openen meubelkist af, terwijl jij er een elseif bij moet zetten.

Jouw code is nu equivalent aan if(m instanceof Kast), alleen dan zonder de daarvoor aangerijkte hulpmiddelen uit de taal zelf.

[ Voor 6% gewijzigd door ACM op 06-04-2011 20:52 ]


Acties:
  • 0 Henk 'm!

  • Big Joe
  • Registratie: Maart 2004
  • Laatst online: 02-08 15:22
Amras schreef op woensdag 06 april 2011 @ 20:47:
Waarom maakt een Servieskast een nieuwe Kast en opent deze, terwijl er wordt gevraagd om de Servieskast te openen?
Je hebt gelijk, ik kwam erachter dat dit inderdaad niet klopte, hier is een nieuwe versie:
In deze versie kan je categorieen aangeven, zoals een kast of deur. Als de applicatie dan ziet dat de classname het woord "Kast" bevat, dan weet hij dat de superclass een kast is.
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
    public class Meubel
    {
        public void plaats()
        {
            Console.WriteLine("Meubel geplaatst");
        }
    }

    class Kast : Meubel
    {
        public void open()
        {
            Console.WriteLine("Kast geopend");
        }
    }

    class ServiesKast : Kast
    {
    }

    class Bank : Meubel
    {
    }

    static class MeubelCheckerHelper
    {
        public static String openableMeubels = "kast;deur";
        public static bool isOpenableMeubel(Meubel meubel)
        {
            foreach (String meubelclass in openableMeubels.Split(';'))
            {
                if (meubel.GetType().ToString().ToLower().Contains(meubelclass.ToLower()))
                {
                    return true;
                }
            }
            return false;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Kast meubel1 = new Kast();
            ServiesKast meubel2 = new ServiesKast();
            List<Meubel> meubels = new List<Meubel>();
            meubels.Add(meubel1);
            meubels.Add(meubel2);
            foreach (Meubel m in meubels)
            {
                if (MeubelCheckerHelper.isOpenableMeubel(m))
                {
                    foreach (String meubelclass in MeubelCheckerHelper.openableMeubels.Split(';'))
                    {
                        if (m.GetType().ToString().ToLower().Contains("kast"))
                        {
                            Kast kast = (Kast)m;
                            kast.open();
                        }
                    }
                }
            }
            Console.ReadKey();
        }
    }

[ Voor 4% gewijzigd door Big Joe op 06-04-2011 21:01 ]


Acties:
  • 0 Henk 'm!

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
Woy schreef op woensdag 06 april 2011 @ 19:57:
[...]

Hoe zie je het dan voor je? Natuurlijk is een Kamer ( o.i.d. ) niet de aangewezen class om meubels te openen, maar als er bijvoorbeeld een Persoon is die dat zou doen, dan moet die alsnog uit de kamer alle IOpenable objecten verkrijgen, en dan heb je daar alsnog iets van instanceof voor gebruiken.
Je hoeft alleen maar instanceof te doen als je te maken hebt met de generieke verzameling meubels. Als je een Opener class hebt die een collectie Openables beheert, kun je daar prima Kasten (implements Openable) aan toevoegen.
Big Joe schreef op woensdag 06 april 2011 @ 20:52:
[...]


Je hebt gelijk, ik kwam erachter dat dit inderdaad niet klopte, hier is een nieuwe versie:
Of je loopt te trollen, of je hebt een plaat voor je kop die ze in Japan graag zouden willen hebben om die reactors af te schermen...

Dit kun je niet serieus menen. |:(

[ Voor 45% gewijzigd door Herko_ter_Horst op 06-04-2011 20:56 ]

"Any sufficiently advanced technology is indistinguishable from magic."


Acties:
  • 0 Henk 'm!

  • Alex)
  • Registratie: Juni 2003
  • Laatst online: 21-08 11:20
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
using System;
using System.Collections.Generic;

namespace MeubelOO
{
    interface IOpenable
    {
        void Open();
    }

    interface ISittable
    {
        void SitOn();
    }

    interface IRollable
    {
        void Roll();
    }

    interface ILockable
    {
        void ToggleLock();
    }

    abstract class Meubel
    {
        public double Width { get; set; }
        public double Height { get; set; }
    }

    class Kast : Meubel, IOpenable
    {
        public void Open()
        {
            Console.WriteLine(this.GetType().Name + ": Ik ben nu open.");
        }
    }

    class Dressoir : Kast
    {
    }

    class Archiefkast : Kast
    {
    }

    class Kantoorkast : Archiefkast, ILockable
    {
        public bool IsLocked { get; private set; }
        public void ToggleLock()
        {
            Console.WriteLine(this.GetType().Name + (IsLocked ? ": Ik ben van het slot gehaald." : ": Ik ben op slot gedaan."));

            IsLocked = !IsLocked;
        }
    }

    class Stoel : Meubel, ISittable
    {
        public void SitOn()
        {
            Console.WriteLine(this.GetType().Name + ": Iemand zit nu op mij.");
        }
    }

    class Bureaustoel : Stoel, IRollable
    {
        public void Roll()
        {
            Console.WriteLine(this.GetType().Name + ": They see me rollin'");
        }
    }

    class LuxeBureaustoel : Bureaustoel
    {
    }

    class Program
    {
        static void Main(string[] args)
        {
            var alleMeubels = new List<Meubel>
                                  {
                                      new Kast(),
                                      new Dressoir(),
                                      new Archiefkast(),
                                      new Kantoorkast(),
                                      new Stoel(),
                                      new Bureaustoel(),
                                      new LuxeBureaustoel()
                                  };

            foreach (var meubel in alleMeubels)
            {
                if (meubel is IOpenable)
                {
                    ((IOpenable)meubel).Open();
                }

                if (meubel is ISittable)
                {
                    ((ISittable)meubel).SitOn();
                }

                if (meubel is IRollable)
                {
                    ((IRollable)meubel).Roll();
                }

                if (meubel is ILockable)
                {
                    ((ILockable)meubel).ToggleLock();
                }
            }

            Console.ReadKey();
        }
    }
}


Kast: Ik ben nu open.
Dressoir: Ik ben nu open.
Archiefkast: Ik ben nu open.
Kantoorkast: Ik ben nu open.
Kantoorkast: Ik ben op slot gedaan.
Stoel: Iemand zit nu op mij.
Bureaustoel: Iemand zit nu op mij.
Bureaustoel: They see me rollin'
LuxeBureaustoel: Iemand zit nu op mij.
LuxeBureaustoel: They see me rollin'


Ik zie echt niet in hoe je dit efficiënt kunt bereiken zónder te kijken of een bepaalde interface geïmplementeerd wordt. Dat gedoe met strings is wel enorm lelijk en zeker niet zaligmakend, zie mijn voorbeeldje met een Dressoir. Het is zeker een kast, maar er zit geen Kast in de naam. ;)

We are shaping the future


Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 08-09 11:33
Big Joe schreef op woensdag 06 april 2011 @ 20:52:
[...]


Je hebt gelijk, ik kwam erachter dat dit inderdaad niet klopte, hier is een nieuwe versie:
In deze versie kan je categorieen aangeven, zoals een kast of deur. Als de applicatie dan ziet dat de classname het woord "Kast" bevat, dan weet hij dat de superclass een kast is.
Zo dus nu kan ik ook boeken in mijn Kasteel :+ zetten? ... Het blijft gewoon niet de goede manier, je wilt types/inheritance vergelijken, vergelijk dan types, geen strings.

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Herko_ter_Horst schreef op woensdag 06 april 2011 @ 20:54:
[...]
Je hoeft alleen maar instanceof te doen als je te maken hebt met de generieke verzameling meubels. Als je een Opener class hebt die een collectie Openables beheert, kun je daar prima Kasten (implements Openable) aan toevoegen.
Maar hoe komt die Opener aan de collectie? Waarschijnlijk word er op een bepaald moment bedacht dat alle Openable objecten in een Kamer geopend moeten worden ( Of alleen de eerste Container die Openable is waar genoeg ruimte is om iets in op te bergen ). Bij het creëren van de objecten, of het toevoegen aan de Kamer weet je immers nog niet wat er allemaal met de objecten gaat gebeuren.

Nogmaals: Het is goed om te zorgen dat je collectie niet te generiek is, maar je ontkomt er gewoon niet altijd aan.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Big Joe schreef op woensdag 06 april 2011 @ 20:52:
In deze versie kan je categorieen aangeven, zoals een kast of deur
En inderdaad, zoals hierboven al gezegd, ga je dan nat bij een Kasteel. Seriously; je hebt drastisch (bij)scholing nodig als je ervan overtuigd bent dat dit goede code is. En zoals anderen al zeiden:je bent misschien best een goede programmeur, maar dit gaat nergens over en is echt beneden peil. Al zit je 50 jaar in 't vak; als je sinds dag 1 niet meer hebt bijgeleerd dan maakt 't je niet nu een goede programmeur. Het spijt me zeer. Op dit vlak moet je gewoon wat leren zo blijkt. Neem dat als een vent en leer er van en doe er iets mee. Daar word je sterker en beter van :)

C#:
1
public static String openableMeubels = "kast;deur"; 

Dit is gewoon een poor-mans wannabe-interface-iets. Gebruik dan gewoon een interface; daar is 't voor.

[ Voor 19% gewijzigd door RobIII op 06-04-2011 22:04 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
Woy schreef op woensdag 06 april 2011 @ 21:49:
[...]

Maar hoe komt die Opener aan de collectie? Waarschijnlijk word er op een bepaald moment bedacht dat alle Openable objecten in een Kamer geopend moeten worden ( Of alleen de eerste Container die Openable is waar genoeg ruimte is om iets in op te bergen ). Bij het creëren van de objecten, of het toevoegen aan de Kamer weet je immers nog niet wat er allemaal met de objecten gaat gebeuren.

Nogmaals: Het is goed om te zorgen dat je collectie niet te generiek is, maar je ontkomt er gewoon niet altijd aan.
De Opener komt aan de collectie doordat objecten er bij creatie ingestopt worden. Dit is uiteraard afhankelijk van het domein. Je zult dus per domein moeten analyseren wat de juiste aanpak is. Instanceof is daarbij een indicatie dat er mogelijk nog iets scheef zit.

Stel dat we het hebben over een tekst-RPG waarin je van Kamer naar Kamer kan gaan. In een Kamer staan Meubels. In een Kamer zijn er ook objecten die open kunnen (c.q. waar de speler mee kan interacteren). Voor de beschrijving zal de Kamer een collectie van Meubels bevatten. Daarnaast bevat de Kamer (of mogelijk een andere klasse) een collectie met Openables. Hierin zitten niet alleen de Kasten (of andere Meubels-die-open-kunnen), maar bijv. ook Boeken, Ramen en Deuren.

Op het moment dat je de Kamer vult, kun je de Kast (die Openable implementeert) simpelweg in beide collecties stoppen.

Iedereen neemt nu die ene generieke collectie van meubels als uitgangspunt. Dan kom je niet zo gauw af van instanceof (of een variant daarop). Je moet naar de requirements kijken om te bepalen of die collectie daar wel terecht staat.

[ Voor 9% gewijzigd door Herko_ter_Horst op 06-04-2011 22:08 ]

"Any sufficiently advanced technology is indistinguishable from magic."


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Herko_ter_Horst schreef op woensdag 06 april 2011 @ 22:02:
[...]
Op het moment dat je de Kamer vult, kun je de Kast (die Openable implementeert) simpelweg in beide collecties stoppen.
Hoe zie je dat vullen dan voor je
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Kamer
{
    void Add(Meubel m)
    {
        meubels.Add(m);
        //Wat als m hier ook een IOpenable is?
    }

    void Add(IOpenable o)
    {
        openables.Add(o);
        //Hoe voeg je hier toe aan meubels? Je weet immers niet zeker of "o" ook een meubel is
    }
}
Iedereen neemt nu die ene generieke collectie van meubels als uitgangspunt. Dan kom je niet zo gauw af van instanceof (of een variant daarop). Je moet naar de requirements kijken om te bepalen of die collectie daar wel terecht staat.
Tuurlijk, daar ben ik het met je eens. Als je bij creatie al weet in welke categorieën je het kan indelen, moet je dat zeker niet laten. Maar je komt dit soort situaties IMHO toch regelmatig tegen.

[ Voor 27% gewijzigd door Woy op 06-04-2011 22:14 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
Woy schreef op woensdag 06 april 2011 @ 22:11:
[...]

Hoe zie je dat vullen dan voor je
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Kamer
{
    void Add(Meubel m)
    {
        meubels.Add(m);
        //Wat als m hier ook een IOpenable is?
    }

    void Add(IOpenable o)
    {
        openables.Add(o);
        //Hoe voeg je hier toe aan meubels? Je weet immers niet zeker of "o" ook een meubel is
    }
}
Iemand maakt die Kast. Die weet dus dat Kast zowel een Meubel als een Openable is en kan daarom beide methodes aanroepen.

"Any sufficiently advanced technology is indistinguishable from magic."


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Herko_ter_Horst schreef op woensdag 06 april 2011 @ 22:15:
[...]

Iemand maakt die Kast. Die weet dus dat Kast zowel een Meubel als een Openable is en kan daarom beide methodes aanroepen.
Dat zou kunnen, maar dat is ook foutgevoelig, immers kan er dan een Meubel in de kamer staan die Openable is, maar die door de Opener niet meer geopend kan worden. Als een class immers later alsnog Openable gaat implementeren word er geheid vergeten om die 2e Add aanroep toe te voegen. En je gaat er in dat geval ook van uit dat de gene die de Kast maakt ook degene is die hem in de Kamer plaatst. Misschien komt hij wel uit een MeubelFactory, en voor die class is het niet interessant dat het een Openable is, voor de Kamer blijkbaar wel, en dus zal die daarop moeten controleren.

Het staat IMHO netter om in de Kamer class een instanceof te gebruiken, dan om te verplichten dat hij 2x aan de Kamer toegevoegd moet worden.

Het is ook niet dat ik wil zeggen dat je altijd maar instanceof moet gebruiken. Het is best goed om je af te vragen of het op die plek wel de beste oplossing is. Maar ik moet toch zeggen dat ik toch wel regelmatig plekken tegenkom waar ik het gebruik.

[ Voor 25% gewijzigd door Woy op 06-04-2011 22:29 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Big Joe schreef op woensdag 06 april 2011 @ 20:52:
Je hebt gelijk, ik kwam erachter dat dit inderdaad niet klopte, hier is een nieuwe versie:
In deze versie kan je categorieen aangeven, zoals een kast of deur. Als de applicatie dan ziet dat de classname het woord "Kast" bevat, dan weet hij dat de superclass een kast is.
En een dressoir? Die kan niet geopend worden? En een kastalein daar steek je maar een breekijzer in?

Ik hoop van harte dat je loopt te trollen. Als je echt denkt dat dit correct ben je gewoon de slechtste Java developer die ik ooit gezien heb, en ik heb een HOOP slechte Java code gezien.

https://niels.nu


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Big Joe schreef op woensdag 06 april 2011 @ 20:12:
Het is een kleine opoffering die je moet maken als je echt om de performance van je applicatie geeft.
Ok, wacht, je zegt iets te geven om de performance van een applicatie, maar toch ga je élke keer een enkele string splitten op ";", die in een array zetten, er overheen lopen, en de array vervolgens weer weggooien.

Vertel me eens, hoe heeft jouw aanpak precies geholpen met het verbeteren van de performance?

Als je al zo eigenwijs wilt zijn om je eigen "pattern" aan te houden, doe het dan alsjeblieft gewoon zo:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    static class MeubelCheckerHelper 
    { 
        public static Type[] openableMeubels = { typeof(Kast), /* ... */ }; 
        public static bool isOpenableMeubel(Meubel meubel) 
        { 
            foreach (Type meubelclass in openableMeubels) 
            { 
                if (meubelclass.IsInstanceOfType(meubel))
                { 
                    return true; 
                } 
            } 
            return false; 
        } 
    } 

Dan werkt het ook nog als 'meubel' een subclass is van Kast, je kunt naar hartelust refactoren, en het performt ook nog eens een stuk beter.

[ Voor 43% gewijzigd door .oisyn op 06-04-2011 23:22 ]

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!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
.oisyn schreef op woensdag 06 april 2011 @ 23:10:
[...]
Dan werkt het ook nog als 'meubel' een subclass is van Kast, je kunt naar hartelust refactoren, en het performt ook nog eens een stuk beter.
Maar dan nog heb je het probleem dat je wel weet dat een specifiek meubel te openen is, maar weet je nog niet hoe je hem kunt openen. Dus zul je met reflection of dynamic types aan de gang moeten, of alsnog een interface IOpenable hebben waar je heen kunt casten.

C#:
1
2
3
4
5
Meubel b = new Kast();
if(MeubelHelper.IsOpenable(b))
{
    b.Open();//Compiler error
}

Als je al weet dat het een Kast is dan heeft het geen nut om IsOpenable te doen, en als je het niet weet, dan kun je er niks mee dat hij Openable is ( Behalve als er dus een interface is ;) )

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 12-09 10:54

Janoz

Moderator Devschuur®

!litemod

.oisyn schreef op woensdag 06 april 2011 @ 23:10:

Als je al zo eigenwijs wilt zijn om je eigen "pattern" aan te houden, doe het dan alsjeblieft gewoon zo:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    static class MeubelCheckerHelper 
    { 
        public static Type[] openableMeubels = { typeof(Kast), /* ... */ }; 
        public static bool isOpenableMeubel(Meubel meubel) 
        { 
            foreach (Type meubelclass in openableMeubels) 
            { 
                if (meubelclass.IsInstanceOfType(meubel))
                { 
                    return true; 
                } 
            } 
            return false; 
        } 
    } 
Java variant daarvan is
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    static class MeubelCheckerHelper 
    { 
        public static Class[] openableMeubels = { Kast.class, /* ... */ }; 
        public static bool isOpenableMeubel(Meubel meubel) 
        { 
            for(Class meubelclass: openableMeubels) 
            { 
                if (meubelclass.isInstance(meubel))
                { 
                    return true; 
                } 
            } 
            return false; 
        } 
    }


Enige voordeel is dat deze code tenminste nog refactor vriendelijk 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!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
offtopic:
@Janoz: Java kent die vorm van foreach toch niet?

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 12-09 10:54

Janoz

Moderator Devschuur®

!litemod

oepsie... Maar deze vorm wel (/me tikt altijd wel foreach om op die manier het eclipse template aan te roepen)

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!

  • ThaNOD
  • Registratie: Februari 2005
  • Laatst online: 17-03 14:04
Om nog even een schop na te geven:

Je kan ook generics gebruiken!
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package area51;

import java.util.LinkedList;
import java.util.List;

public class Kamer {
    public static abstract class Meubel {}
    public static interface Openable {
        void open();
    }
    public static class Kast extends Meubel implements Openable {
        @Override
        public void open() {
            System.out.println("Kast is geopend");
        }
    }
    
    public static class NarniaKast extends Kast {
        @Override
        public void open() {
            System.out.println("Je hebt narnia gevonden");
        }
    }
    
    public static class Kist extends Meubel implements Openable {
        @Override
        public void open() {
            System.out.println("Ik kan ook een kist openen");
        }
    }
    
    public static void main(String... args) {
        List<Kast> kasten = new LinkedList<Kast>();
        kasten.add(new Kast());
        kasten.add(new Kast());
        kasten.add(new NarniaKast());
        kasten.add(new Kast());
        openMeubels(kasten);
        
        openMeubels(verzamelOpenableMeubels(new Kast(), new NarniaKast(), new Kist()));
    }
    
    public static <T extends Meubel & Openable> List<T> verzamelOpenableMeubels(T ...ts){
        List<T> list = new LinkedList();
        for (T t:ts)
            list.add(t);
        return list;
    }
    
    public static <T extends Meubel & Openable> void openMeubels(Iterable<T> list){
        for (T t:list)
            t.open();
    }
}


owkee, het verdient geen prijs en geeft een paar warnings maar het compiled en het runt :+

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Woy schreef op donderdag 07 april 2011 @ 09:01:
Als je al weet dat het een Kast is dan heeft het geen nut om IsOpenable te doen, en als je het niet weet, dan kun je er niks mee dat hij Openable is ( Behalve als er dus een interface is ;) )
OMG ja daar had ik nog niet eens bij stilgestaan. Dat stuk dat Big Joe na de IsOpenable() dan alsnog gaat kijken of het een Kast is met een specifieke cast had ik ook helemaal gemist. Mijn god, wat heb je er dan überhaupt aan :? 8)7

The plot thickens... :+

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!

  • Vinnienerd
  • Registratie: Juli 2000
  • Laatst online: 22:14
Big Joe schreef op woensdag 06 april 2011 @ 20:12:
[...]
Verder vind ik het beneden peil dat jullie mijn code op zo'n negatieve manier afkraken. Ik zit al 15 jaar in het vak en heb nog nooit negatieve feedback gehad op mijn code!
Wat is het nou? Hoe kan feedback leveren beneden pijl zijn? Dat jij nog nooit (negatieve) feedback hebt gehad, maakt nog niet dat jij gelijk hebt.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Vinnienerd schreef op donderdag 07 april 2011 @ 12:18:
[...]

Wat is het nou? Hoe kan feedback leveren beneden pijl zijn? Dat jij nog nooit (negatieve) feedback hebt gehad, maakt nog niet dat jij gelijk hebt.
Het betekent alleen dat 'ie geen mensen kent die op hetzelfde niveau of hoger programmeren. En dat is eerder slecht voor je ontwikkeling dan goed... Ik moet er niet aan denken dat ik een weekje voorbij laat gaan zonder kritiek van mijn collega's, laat staan 15 jaar zonder kritiek. :X

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Armageddon_2k
  • Registratie: September 2002
  • Laatst online: 10-09 15:29

Armageddon_2k

Trotse eigenaar: Yamaha R6

Ach 't is Kaddafi toch ook prima afgegaan, en die zat een jaar of 40 prima op zn plek zonder commentaar :+

Acties:
  • 0 Henk 'm!

  • Vinnienerd
  • Registratie: Juli 2000
  • Laatst online: 22:14
Armageddon_2k schreef op donderdag 07 april 2011 @ 13:08:
Ach 't is Kaddafi toch ook prima afgegaan, en die zat een jaar of 40 prima op zn plek zonder commentaar :+
*kuch* feedback *kuch*

Acties:
  • 0 Henk 'm!

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:07
Big Joe schreef op woensdag 06 april 2011 @ 20:12:
[...]


Bij mij op mijn werk gebruiken we het waterval model en is dit niet van toepassingen. Klassendiagrammen en ontwerpen worden van tevoren opgezet met UML, zodat namen vaststaan en nooit zullen veranderen. Het is een kleine opoffering die je moet maken als je echt om de performance van je applicatie geeft.
Sure ... Programma-code is een organisch iets. Requirements veranderen na verloop van tijd, en een naam die gisteren zinnig was, kan morgen plots helemaal nergens meer opslaan. Dan ga je mij niet zeggen dat je bij code-wijzigingen om die veranderende functionaliteit te implementeren, die class niet gaat refactoren en een andere naam geven ...

Of ... Jullie requirements veranderen nooit, en jullie code is gebeiteld in steen ? Eens gereleased komen er nooit nieuwe versies ?
Een helper is in dit geval een soort controller die de applicatie helpt om te bepalen welke meubelen een kast zijn.
Een ugly implementatie van een instanceof() operator dus ?

https://fgheysels.github.io/


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Angstvallig stil opeens :)

https://niels.nu


Acties:
  • 0 Henk 'm!

  • Caelorum
  • Registratie: April 2005
  • Laatst online: 00:22
Misschien heeft hij het laten zien aan een collega en heeft die hetzelfde gezegd als de mensen in dit topic. Ik denk dat zelfs de leraren op het HBO dit een WTF vinden (en die kunnen ook behoorlijk wat troep produceren hoor :P)

Acties:
  • 0 Henk 'm!

Verwijderd

offtopic:
yay @ "daily wtf"-tag :)

Acties:
  • 0 Henk 'm!

  • Killemov
  • Registratie: Januari 2000
  • Laatst online: 24-08 23:40

Killemov

Ik zoek nog een mooi icooi =)

Woy schreef op donderdag 07 april 2011 @ 09:52:
offtopic:
@Janoz: Java kent die vorm van foreach toch niet?
Janoz schreef op donderdag 07 april 2011 @ 09:58:
oepsie... Maar deze vorm wel (/me tikt altijd wel foreach om op die manier het eclipse template aan te roepen)
Heeey ... Had Janoz nou eerst echt iets als "foreach" staan en heeft hij dat later gewijzigd zonder dat wij dat kunnen zien of bedoelde Woy nu dat hij de ":" manier van itereren niet kent?

In geval Janoz, foei, in geval Woy, dat zit er in sinds 1.5.

En verder heeft .oisyn he-le-maal gelijk dat je het steeds parsen van strings om iets typeof/instanceof-achtigs te krijgen echt niet moet willen. Gewoon goed gebruik maken van interfaces.

Kijk, onderaan, bij normale stervelingen zie je tenminste wel of er iets in het bericht is gehackt.

[ Voor 17% gewijzigd door Killemov op 08-04-2011 21:47 ]

Hey ... maar dan heb je ook wat!


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12-09 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ook bij jou als je minder dan x% hebt geëdit zie je het niet (x=2 ofzo?)

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: 12-09 10:54

Janoz

Moderator Devschuur®

!litemod

Kilermov en .oisyn hebben gelijk ;)

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

Pagina: 1 2 Laatste