[JAVA] Inheritance vraag

Pagina: 1 2 Laatste
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Maethor2
  • Registratie: Augustus 2010
  • Laatst online: 12-06-2024
Ik heb een denk ik simpele vraag over inheritance in java waar ik niet echt aan uit raak.

Ter illustratie hebben we een klasse meubel en een klasse kast die er als volgt uitzien:

Klasse Meubel:

Java:
1
2
3
4
5
6
public class Meubel {

    public void plaats() {
        System.out.println("meubel geplaatst");
    }
}


Klasse kast:

Java:
1
2
3
4
5
6
7
8
9
10
11
public class Kast extends Meubel {

    @Override
    public void plaats() {
        System.out.println("kast geplaatst");
    }

    public void open() {
        System.out.println("kast geopend");
    }
}


Wanneer we nu een array maken van meubels en we plaatsen er een kast in kan ik wel een meubel plaatsen maar deze niet opendoen.

Java:
1
2
3
4
5
6
7
8
9
10
11
Meubel[] woonkamer = new Meubel[10];

Meubel[4] = new Meubel();
Meubel[5] = new Kast();

Meubel[4].plaats(); // Output --> meubel geplaatst
Meubel[5].plaats(); // Output --> kast geplaatst
Meubel[5].open(); // Wil niet compilen

Kast kast = new kast();
kast.open(); // Output --> kast geopend


Een kast is ook een meubel, dus die zou zoals hierboven ook gedaan wordt probleemloos in de meubel array moeten werken. Waarom kan ik dan de methode open niet uitvoeren. Het object waarop ik het wil uitvoeren is immers een kast.

Het enige wat ik op dit moment kan bedenken is dat je met een array van meubelen zit en dan ook beperkt bent tot de methoden in die klasse, maar dat geeft nog altijd niet aan waarom dat zo is.

Acties:
  • 0 Henk 'm!

  • michiel_
  • Registratie: Juli 2005
  • Niet online
Je spreekt het Kast-object aan als Meubel. Op het moment van compilen weet Java alleen maar zeker dat het om een Meubel object gaat, welke de methode open() niet heeft, en dus niet wil compileren.

Op het moment dat je zeker weet dat het een Kast is, kan je hem casten (hoe toepasselijk in dit geval). In het volgende voorbeeld zijn dat de haakjes.
Java:
1
2
Kast k = (Kast) Meubel[5];
k.open();


Mooie referentie: http://download.oracle.co...ava/IandI/subclasses.html (laatste paragraaf gaat over casten)

Acties:
  • 0 Henk 'm!

  • Sihaya
  • Registratie: Juni 2001
  • Niet online

Sihaya

Pasfoto:

Maethor2 schreef op maandag 04 april 2011 @ 21:57:
...

Het enige wat ik op dit moment kan bedenken is dat je met een array van meubelen zit en dan ook beperkt bent tot de methoden in die klasse, maar dat geeft nog altijd niet aan waarom dat zo is.
Dit is op zich je antwoord. Het array is van het type Meubel[] waardoor er alleen van uit gegaan kan worden dat ieder object in het array tenminste van het type Meubel is.

Overigens kun je wel gebruik maken van downcasting via de cast operator, bijvoorbeeld:

Java:
1
2
3
if (Meubel[5] instanceof Kast) {
  ((Kast)Meubel[5]).open();
}

signature has expired


Acties:
  • 0 Henk 'm!

  • themole
  • Registratie: Juli 2010
  • Laatst online: 19-11-2023
Zoals je zelf al aangeeft ben je idd gebonden aan de methodes van Meubel als je een kast in de Meubelarray zet. Met de volgende code zou het wel moeten werken

Java:
1
2
3
4
5
6
7
8
9
Meubel[] woonkamer = new Meubel[10];

Meubel[4] = new Meubel();
Meubel[5] = new Kast();

Meubel[4].plaats(); // Output --> meubel geplaatst
Meubel[5].plaats(); // Output --> kast geplaatst
Kast kast = (Kast) Meubel[5];
kast.open(); // Output --> kast geopend


De reden dat het zo is heeft volgensmij te maken met de types. De javac kijkt volgensmij naar het huidige type, niet naar het gedeclareerde type. Het huidige type in de meubelarray is gewoon een meubel. Je moet de javac dus vertellen dat het een Kast is. :P Als het btw geen Kast is wordt er door java op runtime een ClassCastException geworpen.

[ Voor 5% gewijzigd door themole op 04-04-2011 22:16 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Sihaya schreef op maandag 04 april 2011 @ 22:12:
Java:
1
2
3
if (Meubel[5] instanceof Kast) {
  ((Kast)Meubel[5]).open();
}
Mooier is om een interface Openable te gebruiken. Dit kan dan worden gebruikt voor verschillende soorten meubelen die niet direct gerelateerd zijn maar wel vergelijkbare eigenschappen bezitten. Een servieskast versus een reiskist bijvoorbeeld. Een boekenkast is wel een kast maar kan niet worden geopend. Niet elke kast zou dus Openable implementeren.

En een kamer is geen array van meubelen, een kamer heeft misschien een eigenschap die een collection is die meubels bevatten:

Java:
1
2
3
4
5
6
7
public class Kamer {
    private Collection<Meubel> meubels = new HashSet<Meubel>();

    public Collection<Meubel> getMeubels() {
        return this.meubels;
    }
}

[ Voor 22% gewijzigd door Verwijderd op 04-04-2011 22:34 ]


Acties:
  • 0 Henk 'm!

  • Maethor2
  • Registratie: Augustus 2010
  • Laatst online: 12-06-2024
Bedankt voor de antwoorden, het principe is duidelijk zo ook de gegeven manieren om toch te doen wat ik uiteindelijk wil. Het voorbeeld zelf was eerder om het principe te tonen.

Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Verwijderd schreef op maandag 04 april 2011 @ 22:23:
[...]

Mooier is om een interface Openable te gebruiken.
Hij is overduidelijk bezig met een schoolopdracht. Dan is het niet verstanding hem te verwarren met stof die hij waarschijnlijk een paar lessen later krijgt. Wij hebben vrijwel exact dezelfde opdracht (13 jaar geleden) gedaan met voertuigen en auto's. Een interface toepassen was geen optie, je hebt je aan de opdracht te houden :)

Ik ben het er daarnaast niet mee eens dat het 'mooier' is een interface te gebruiken. Er is hier juist een voorbeeld gecreerd waar een superclass ook daadwerkelijk een methode implementeert. Zoals je weet implementeert een interface niks.

https://niels.nu


Acties:
  • 0 Henk 'm!

Verwijderd

Hydra schreef op maandag 04 april 2011 @ 23:15:

Hij is overduidelijk bezig met een schoolopdracht. Dan is het niet verstanding hem te verwarren met stof die hij waarschijnlijk een paar lessen later krijgt. Wij hebben vrijwel exact dezelfde opdracht (13 jaar geleden) gedaan met voertuigen en auto's. Een interface toepassen was geen optie, je hebt je aan de opdracht te houden :)
Wat een kutexcuus. Als je wilt weten of je een methode aan kunt roepen, moet je weten dat het een class is die die methode heeft. En als je methode niet zeer specifiek alleen voor een speciale class is, kun je beter een interface gebruiken. Zoals ik al in mijn voorbeeld aangaf is een reiskist geen kast, maar kan hij wel worden geopend. Welke superclass zou jij voorstellen om die functionaliteit te omschrijven?
Ik ben het er daarnaast niet mee eens dat het 'mooier' is een interface te gebruiken. Er is hier juist een voorbeeld gecreerd waar een superclass ook daadwerkelijk een methode implementeert. Zoals je weet implementeert een interface niks.
Uiteraard weet ik dat. Maar jij hoort te weten dat als een class een bepaalde interface implementeert, die methode ook moet worden geïmplementeerd, maar dat dat voor de aanroep niet uitmaakt. Generieke functionaliteit wordt beschreven in interfaces. Het mooiste daarvan is dat een class meerdere interfaces kan implementeren en dat het voor de applicatie niet uitmaakt welke dat zijn.

Openable, Rollable, Stackable, Inflatable, Sittable

Wil je een generieke class hebben voor stoelen en banken? Prima! Maakt een abstract class Seat implements Sittable (met de implementatie voor takeSeat()), een public class Chair extends Seat, een public class Sofa extends Seat, een public class OfficeChair extends Chair implements Rollable (met de implementatie voor roll()).

Interfaces sluiten het gebruik van (abstract) classes niet uit! Je hebt de classes net zo hard nodig, maar je maakt de implementatie van de functie minder belangrijk omdat het type object er niet meer toe doet. Het gaat vaak niet om wat iets is maar wat je ermee kunt.

Acties:
  • 0 Henk 'm!

  • Pepperoni
  • Registratie: April 2010
  • Laatst online: 05-09 15:53
Even deze voor je uit m'n bookmarks gehaald: http://forum.codecall.net...pcasting-downcasting.html
Vond hem duidelijk toen ik hier destijds mee zat, wellicht heb je er nog wat aan.

Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Goed begin van je post ook. :w

https://niels.nu


Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

Laten we hier die vervelende toon maar meteen droppen. ;)

Overigens hangt het maar net van de leraar af of je wel of niet zomaar ineens een interface kan gebruiken. Je hebt het type leraar waar een goede implementatie en bijbehorende uitleg je bonuspunten geven, en het type leraar dat je strafpunten geeft omdat je je niet strikt aan de opdracht gehouden hebt. Als het inderdaad een schoolopdracht is zal Maethor2 even voor zichzelf uit moeten vogelen of de leraar zo'n oplossing zou kunnen waarderen.

Overigens ben ik het wel met Cheatah's argumenten eens en is een interface voor de open-functionaliteit wel mooier. :)

'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!

  • Maethor2
  • Registratie: Augustus 2010
  • Laatst online: 12-06-2024
Het is niet voor een schoolopdracht, ik was gewoon nieuwsgierig en heb dit als simpel voorbeeld gebruikt. Het is niet de bedoeling dat bovenstaand voorbeeld ergens toegepast wordt, het was enkel om mijn punt duidelijk te maken.

Acties:
  • 0 Henk 'm!

Verwijderd

Prima, het is op zich ook een goed voorbeeld en een duidelijke vraag.

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();
    }
}


Dit zou ongeveer zijn wat ik ervan zou maken. Ik wil het best nog even nader toelichten maar heb nu geen tijd :)

Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Maethor2 schreef op dinsdag 05 april 2011 @ 08:28:
Het is niet voor een schoolopdracht, ik was gewoon nieuwsgierig en heb dit als simpel voorbeeld gebruikt. Het is niet de bedoeling dat bovenstaand voorbeeld ergens toegepast wordt, het was enkel om mijn punt duidelijk te maken.
Ah, okay. Ik kreeg een flashback naar 13 jaar terug toen we ongeveer dezelfde opdracht kregen, maar dan met Auto's. :)
NMe schreef op dinsdag 05 april 2011 @ 03:07:
Overigens ben ik het wel met Cheatah's argumenten eens en is een interface voor de open-functionaliteit wel mooier. :)
Daar ben ik het ook zeker mee eens. Het probleem destijds was dat een beetje leraar bij ons gewoon jouw werk naast een sjabloon legde, en als dat niet min of meer overeen kwam je aftrek van punten kreeg. Lang leve HBO informatica.

Maargoed, het was geen schoolopdracht kennelijk :)

https://niels.nu


Acties:
  • 0 Henk 'm!

Verwijderd

Hydra schreef op dinsdag 05 april 2011 @ 10:21:

Daar ben ik het ook zeker mee eens. Het probleem destijds was dat een beetje leraar bij ons gewoon jouw werk naast een sjabloon legde, en als dat niet min of meer overeen kwam je aftrek van punten kreeg. Lang leve HBO informatica.
Dat is ook het voornaamste probleem dat ik heb met ICT opleidingen. Veel docenten zijn lui die willen dat je iets uit een boekje leert, terwijl iemand die al verder is daar juist door wordt beperkt. Misschien dat ik daarom ook iets minder subtiel reageerde, het zit heel diep ;)

Acties:
  • 0 Henk 'm!

  • bronce
  • Registratie: Januari 2011
  • Laatst online: 16:17
Nog even voor de volledigheid:

Je hebt het gedeclareerde type (statisch) van een variable en het opgeslagen type (dynamisch).
Als je een programma wil compilen wordt er naar het statische type gekeken en als je het uitvoert naar het dynamische type.

Wat hier ook geld is dat een kast een meubel is maar een meubel geen kast. Een meubel kan ook een stoel zijn of iets dergelijks.

Wat wel mag is bijvoorbeeld :
Meubel k = new Kast();
Meubel b = new Bank();

Wat niet mag is:
Kast k = new Meubel();
Bank b = new Meubel();

Dit zal een compileer fout geven namelijk: incompatible types.
Wat je kunt doen is bijvoorbeeld typecasten wat hierboven is uitgelegd.

Als je een programma uitvoert zal een methode altijd eerst uit de laagste klasse uit een overervingshiërarchie
worden gekozen. Als die methode daar niet aanwezig is zal er naar de superklasse worden gekeken.

Wat hier wederom geld is dat er geen methode look up is van een superklasse naar een subklasse.

Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Verwijderd schreef op dinsdag 05 april 2011 @ 11:55:
[...]

Dat is ook het voornaamste probleem dat ik heb met ICT opleidingen. Veel docenten zijn lui die willen dat je iets uit een boekje leert, terwijl iemand die al verder is daar juist door wordt beperkt. Misschien dat ik daarom ook iets minder subtiel reageerde, het zit heel diep ;)
Het is je vergeven ;)

Niet alleen zijn die docenten lui, hun kennisniveau is in de meeste gevallen nauwelijks hoger dan dat van de studenten. Ik weet nog dat we destijds met multithreading bezig gingen en ik al vast wat probeersels aan het maken was (chatservertje) waarbij het e.e.a. gewoon niet lekker werkte. Ik ben met dat baksel naar de docent gegaan, en die kon mij niet helpen omdat hij zelf dat hoorcollege nog niet gehad had. Dan ga je je toch afvragen waar al dat geld aan besteed wordt. Oh ja, een "kunstwerk" op het plein voor de ingang dat 4 miljoen kostte 8)7

Ja, het zit mij ook diep :)

https://niels.nu


Acties:
  • 0 Henk 'm!

  • Maethor2
  • Registratie: Augustus 2010
  • Laatst online: 12-06-2024
Verwijderd schreef op dinsdag 05 april 2011 @ 08:42:
Prima, het is op zich ook een goed voorbeeld en een duidelijke vraag.

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();
    }
}


Dit zou ongeveer zijn wat ik ervan zou maken. Ik wil het best nog even nader toelichten maar heb nu geen tijd :)
Als ik het goed begrijp is openable hier een interface die geimplementeerd wordt door Meubel?

Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Maethor2 schreef op dinsdag 05 april 2011 @ 17:25:
Als ik het goed begrijp is openable hier een interface die geimplementeerd wordt door Meubel?
Yup. Kort door de bocht is het voordeel van interfaces (in Java en .Net) dat je er i.t.t. overerving meerdere kunt implementeren. Het nadeel is dat je in een interface alleen een afspraak maakt over welke methoden een implementatie heeft, je kunt in een interface geen methoden implementeren zoals in een abstract class je dat wel kan.

https://niels.nu


Acties:
  • 0 Henk 'm!

  • Jegorex
  • Registratie: April 2004
  • Laatst online: 03-09 23:24
Maethor2 schreef op dinsdag 05 april 2011 @ 17:25:
[...]


Als ik het goed begrijp is openable hier een interface die geimplementeerd wordt door Meubel?
Nee, het wordt geïmplementeerd door Kast.
Niet elke meubel is te openen, maar in dit voorbeeld is elke kast wel te openen.
Daarom controleer je in regel 8 of je meubel Openable implementeert.

Acties:
  • 0 Henk 'm!

  • Jeanpaul145
  • Registratie: Juli 2007
  • Laatst online: 15-07 14:52
Sihaya schreef op maandag 04 april 2011 @ 22:12:
[...]

Dit is op zich je antwoord. Het array is van het type Meubel[] waardoor er alleen van uit gegaan kan worden dat ieder object in het array tenminste van het type Meubel is.

Overigens kun je wel gebruik maken van downcasting via de cast operator, bijvoorbeeld:

Java:
1
2
3
if (Meubel[5] instanceof Kast) {
  ((Kast)Meubel[5]).open();
}
In de meeste gevallen dat ik dit door Java programmeurs gebruikt heb zien worden was hun abstractiemodel op z'n zachtst gezegd gebrekkig.
Hoewel er ligitieme redenen zijn voor het gebruik van de instanceof operator zijn ze dun gezaaid.
Maethor2 schreef op dinsdag 05 april 2011 @ 17:25:
[...]


Als ik het goed begrijp is openable hier een interface die geimplementeerd wordt door Meubel?
Nope, door Kast, anders kan elk Meubel geopend worden.

@NMe: De meeste codebases waar vaak instanceof gebruikt wordt gebruiken, zoals ik al zei, geen behoorlijke abstractie waardoor in feite de object-georienteerdheid van die codebases compleet teniet wordt gedaan, en dan met name het data-hiding principe. Er worden immers methoden van een object gebruikt die niet in de publieke interface van het gedeclareerde compile-time type van dat object zitten, waardoor een downcast nodig is. De fix is dan ook, zoals hierboven al aangegeven, een behoorlijke interface schrijven die de benodigde functionaliteit aan de interface van het object toevoegt.
Waarom dan nog Java code schrijven? Als een coder er op staat zulke code te schtijven is een imperatieve stijl een betere optie lijkt me.

[ Voor 43% gewijzigd door Jeanpaul145 op 05-04-2011 20:17 ]

:j


Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

Jeanpaul145 schreef op dinsdag 05 april 2011 @ 19:26:
[...]

In de meeste gevallen dat ik dit door Java programmeurs gebruikt heb zien worden was hun abstractiemodel gruwelijk slecht.
Hoewel er ligitieme redenen zijn voor het gebruik van de instanceof operator zijn ze dun gezaaid.
Het valt me op dat je geen enkele uitspraak doet over deze specifieke toepassing ervan en wát er dan zo slecht aan is. Je opmerking is dus compleet niet onderbouwd en heeft daarom dus ook geen enkele waarde in deze 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!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Jegorex schreef op dinsdag 05 april 2011 @ 19:08:
[...]

Nee, het wordt geïmplementeerd door Kast.
Niet elke meubel is te openen, maar in dit voorbeeld is elke kast wel te openen.
Daarom controleer je in regel 8 of je meubel Openable implementeert.
Oh, oops, dat ja.

https://niels.nu


Acties:
  • 0 Henk 'm!

Verwijderd

Hydra schreef op dinsdag 05 april 2011 @ 17:41:
Yup. Kort door de bocht is het voordeel van interfaces (in Java en .Net) dat je er i.t.t. overerving meerdere kunt implementeren. Het nadeel is dat je in een interface alleen een afspraak maakt over welke methoden een implementatie heeft, je kunt in een interface geen methoden implementeren zoals in een abstract class je dat wel kan.
Wat dan natuurlijk wel weer gaat is een default implementatie maken van je interface, en daar naar delegeren vanuit je klassen die de interface moeten implementeren. En met een beetje IDE is dat niet meer werk dan extenden van een abstracte klasse.
Alleen de Javadoc krijg je met dat delegeren niet cadeau ;(

Maar dit heeft natuurlijk niet zoveel meer te maken met de originele vraagstelling

Acties:
  • 0 Henk 'm!

  • Maethor2
  • Registratie: Augustus 2010
  • Laatst online: 12-06-2024
Jegorex schreef op dinsdag 05 april 2011 @ 19:08:
[...]

Nee, het wordt geïmplementeerd door Kast.
Logisch |:( , even niet ver genoeg nagedacht blijkbaar
Verwijderd schreef op dinsdag 05 april 2011 @ 20:14:
Maar dit heeft natuurlijk niet zoveel meer te maken met de originele vraagstelling
De originele vraagstelling is imo zeer goed beantwoord en intussen duidelijk :)

[ Voor 39% gewijzigd door Maethor2 op 05-04-2011 20:34 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Even nog een kleine aanmerking op de eerste post, daarin staat dat Meubel een volwaardige class is, echter vind ik dat dat absoluut een abstract class zou moeten zijn. Puur omdat je hem dan niet op zichzelf kunt instantiëren, de naam staat dat niet toe, vind ik.

Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

Jeanpaul145 schreef op dinsdag 05 april 2011 @ 19:26:
[...]

@NMe: De meeste codebases waar vaak instanceof gebruikt wordt gebruiken, zoals ik al zei, geen behoorlijke abstractie waardoor in feite de object-georienteerdheid van die codebases compleet teniet wordt gedaan, en dan met name het data-hiding principe. Er worden immers methoden van een object gebruikt die niet in de publieke interface van het gedeclareerde compile-time type van dat object zitten, waardoor een downcast nodig is. De fix is dan ook, zoals hierboven al aangegeven, een behoorlijke interface schrijven die de benodigde functionaliteit aan de interface van het object toevoegt.
Waarom dan nog Java code schrijven? Als een coder er op staat zulke code te schtijven is een imperatieve stijl een betere optie lijkt me.
In Verwijderd in "[JAVA] Inheritance vraag" wordt instanceof gebruikt om te kijken of het een object is die de Openable-interface implementeert. Dat lijkt me best een valide manier om het te gebruiken? :) Dat is ook waarom ik hierover doorzaag, aangezien dit volgens mij de "accepted answer" is in dit topic. :)

'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: 16:17
Je kan ook een methode maken in meubel open() die print bijvoorbeeld uit kan niet geopend worden.
En bij klassen die geopend moeten worden kan je die methode overriden.

Hiermee vermijd je dus het gebruik van typecasting en instanceof en het is zo dat instance of en typecasting vermeden moeten worden.

Acties:
  • 0 Henk 'm!

Verwijderd

Ga eens gauw een andere hobby zoeken :D

Acties:
  • 0 Henk 'm!

  • bronce
  • Registratie: Januari 2011
  • Laatst online: 16:17
Een voorbeeld:

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
 
public abstract class Meubel
{
    public abstract void open();
}

public class Bank extends Meubel
{
    public void open()
    {
        System.out.println("Bank kan niet geopend worden");
    }

}

public class Kast extends Meubel
{
    public void open()
    {
        System.out.println("Kast is geopend");
    }
}

public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args)
    {
        Meubel m = new Kast();
        Meubel b = new Bank();

        m.open();
        b.open();
    }

}


uitvoer:
run:
Kast is geopend
Bank kan niet geopend worden
BUILD SUCCESSFUL (total time: 0 seconds)

Je kunt beter nog de hierarchië opsplitsten in een deel dat geopend kan worden en een deel dat dat niet kan zodat je het niet voor elk meubel hoeft de schrijven (wat natuurlijk het doel is van overerving gedupliceerde code vermijden).

Acties:
  • 0 Henk 'm!

  • Jeanpaul145
  • Registratie: Juli 2007
  • Laatst online: 15-07 14:52
NMe schreef op dinsdag 05 april 2011 @ 21:28:
[...]

In Verwijderd in "[JAVA] Inheritance vraag" wordt instanceof gebruikt om te kijken of het een object is die de Openable-interface implementeert. Dat lijkt me best een valide manier om het te gebruiken? :) Dat is ook waarom ik hierover doorzaag, aangezien dit volgens mij de "accepted answer" is in dit topic. :)
Uiteindelijk is het een kwestie van design style en smaak, en evenveel kunst als wetenschap. Persoonlijk vind ik de instanceof-manier tot hele ranzige code leiden. Sterker nog, in mijn Java code heb ik tot nu toe nog nooit instanceof écht nodig gehad voor object oriëntatie zelf.
bronce schreef op dinsdag 05 april 2011 @ 21:40:
Je kan ook een methode maken in meubel open() die print bijvoorbeeld uit kan niet geopend worden.
En bij klassen die geopend moeten worden kan je die methode overriden.

Hiermee vermijd je dus het gebruik van typecasting en instanceof en het is zo dat instance of en typecasting vermeden moeten worden.
Behalve dan dat je dan het contract van de interface/abstracte class waarin de method open() werd gedeclareerd verbreekt en dus niet echt meer OO bezig bent. In jouw code-voorbeeld is het niet alleen zo dat Bank claimt dat ie geopend kan worden (hij heeft immers een open() methode) en kan kan ie dat niet; hij claimt dat ie ge-opend()'d kan worden omdat ie een bepaalde interface implementeert. en kan ie dat niet.

:j


Acties:
  • 0 Henk 'm!

  • bronce
  • Registratie: Januari 2011
  • Laatst online: 16:17
Behalve dan dat je dan het contract van de interface/abstracte class waarin de method open() werd gedeclareerd verbreekt en dus niet echt meer OO bezig bent. In jouw code-voorbeeld is het niet alleen zo dat Bank claimt dat ie geopend kan worden (hij heeft immers een open() methode) en kan kan ie dat niet; hij claimt dat ie ge-opend()'d kan worden omdat ie een bepaalde interface implementeert. en kan ie dat niet.
Ik ben het deels met je eens.
Ten eerste is het misschien beter om een interface te implementeren maar dit is misschien gelijk wat veel "lesstof" voor de topicstarter.
Ten tweede ik wilde alleen laten zien dat je doormiddel van het overriden van methods je instanceof en typecasting kan vermijden. Ik zou de methode net zo goed tryToOpen() kunnen noemen of een interface openable implementeren.

Acties:
  • 0 Henk 'm!

  • Caelorum
  • Registratie: April 2005
  • Laatst online: 20:41
Ik ben geen javaan, maar zelfs ik twijfel aan jouw methode jwgoverg. Zou je wellicht kunnen toevoegen waarom je tegen een OO-principe ingaat alleen om instanceof of typecasting tegen te gaan?
Wat is er zo erg aan typecasting/instanceof in java?

[ Voor 13% gewijzigd door Caelorum op 05-04-2011 23:09 ]


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
bronce schreef op dinsdag 05 april 2011 @ 22:50:
[...]


Ik ben het deels met je eens.
Ten eerste is het misschien beter om een interface te implementeren maar dit is misschien gelijk wat veel "lesstof" voor de topicstarter.
Ten tweede ik wilde alleen laten zien dat je doormiddel van het overriden van methods je instanceof en typecasting kan vermijden. Ik zou de methode net zo goed tryToOpen() kunnen noemen of een interface openable implementeren.
Je hebt goed laten zien hoe het niet moet in ieder geval. Het slaat werkelijk nergens op dat een class een methode aanbied die hij niet uit kan voeren.

https://niels.nu


Acties:
  • 0 Henk 'm!

  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
instanceof-gebruik kan betekenen dat er teveel functionaliteit is samengebracht in één class. Een collectie van Meubels is het vreemd dat je moet weten dan sommige Openable zijn. Nu is dit slechts een voorbeeld, zonder requirements is het lastig te bepalen of dit de meest elegante oplossing is.

instanceof is een code smell. Het kan geen kwaad er kritisch naar te kijken.

"Any sufficiently advanced technology is indistinguishable from magic."


Acties:
  • 0 Henk 'm!

Verwijderd

Jeanpaul145 schreef op dinsdag 05 april 2011 @ 22:37:

Uiteindelijk is het een kwestie van design style en smaak, en evenveel kunst als wetenschap. Persoonlijk vind ik de instanceof-manier tot hele ranzige code leiden. Sterker nog, in mijn Java code heb ik tot nu toe nog nooit instanceof écht nodig gehad voor object oriëntatie zelf.
Kom eens met een vergelijkbaar alternatief zoals jij het zou programmeren, dus zonder instanceof.

Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

bronce schreef op dinsdag 05 april 2011 @ 22:50:
[...]

Ik ben het deels met je eens.
Ten eerste is het misschien beter om een interface te implementeren maar dit is misschien gelijk wat veel "lesstof" voor de topicstarter.
Ten tweede ik wilde alleen laten zien dat je doormiddel van het overriden van methods je instanceof en typecasting kan vermijden. Ik zou de methode net zo goed tryToOpen() kunnen noemen of een interface openable implementeren.
Cheatah zei het al behoorlijk onsubtiel maar als je dit nog steeds beweert na bovenstaande argumenten om het niet te doen dan kun je misschien inderdaad maar beter een andere hobby zoeken. Een methode aanbieden die per definite niet werkt of niets doet slaat nergens op. Mijn auto heeft toch ook geen bedieningspaneel om omhoog/omlaag te gaan alleen omdat bepaalde andere voertuigen wél kunnen vliegen? 8)7

'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!

  • Jeanpaul145
  • Registratie: Juli 2007
  • Laatst online: 15-07 14:52
Verwijderd schreef op dinsdag 05 april 2011 @ 23:30:
[...]

Kom eens met een vergelijkbaar alternatief zoals jij het zou programmeren, dus zonder instanceof.
Al gedaan. Lees goed.

@PissedCapsLock: Kijk anders maar naar RayNBow's voorbeeld hieronder, dat is een goed voorbeeld van hoe je door objectoriëntatie toe te passen instanceofs kan vermijden.

[ Voor 25% gewijzigd door Jeanpaul145 op 06-04-2011 11:43 ]

:j


Acties:
  • 0 Henk 'm!

Verwijderd

Jeanpaul145 schreef op dinsdag 05 april 2011 @ 19:26:
De fix is dan ook, zoals hierboven al aangegeven, een behoorlijke interface schrijven die de benodigde functionaliteit aan de interface van het object toevoegt.
En dan moet je toch nog steeds een instanceof doen op die interface ? Dus hoe zou je met deze aanpak die "ranzige instanceof's" vermijden

Acties:
  • 0 Henk 'm!

  • RayNbow
  • Registratie: Maart 2003
  • Laatst online: 19:59

RayNbow

Kirika <3

Look ma, no instanceofs:
Java:
1
2
3
4
public abstract class Furniture {
    public abstract void install();
    public abstract void accept(FurnitureVisitor v);
}
Java:
1
2
3
4
public class FurnitureVisitor {
    public void visit(Closet c) {}
    public void visit(Couch c) {}
}
Java:
1
2
3
4
5
6
7
8
9
10
public class Couch extends Furniture {
    @Override
    public void install() {
        System.out.println("Couch.install()");
    }
    @Override
    public void accept(FurnitureVisitor v) {
        v.visit(this);
    }
}
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Closet extends Furniture {
    @Override
    public void install() {
        System.out.println("Closet.install()");
    }
    public void open() {
        System.out.println("Closet.open()");
    }
    @Override
    public void accept(FurnitureVisitor v) {
        v.visit(this);
    }
}

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
import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Furniture> ikea = Arrays.asList(new Couch(), 
                                             new Closet(),
                                             new Closet(),
                                             new Couch());
        for (Furniture f : ikea)
            f.accept(new FurnitureVisitor(){
                @Override public void visit(Closet c) {
                    c.install();
                    c.open();
                }
                @Override public void visit(Couch c) {
                    c.install();
                }
            });
    }
}
/*
Prints:
    Couch.install()
    Closet.install()
    Closet.open()
    Closet.install()
    Closet.open()
    Couch.install()
*/

:+

Ipsa Scientia Potestas Est
NNID: ShinNoNoir


Acties:
  • 0 Henk 'm!

  • bronce
  • Registratie: Januari 2011
  • Laatst online: 16:17
Ik weet niet of je het zelf door hebt maar instanceof gaat juist tegen OO principes in omdat je zegt als dit object van deze klasse is doe dit, en als dit object van die klasse is doe dat.
Method overriding is een beter alternatief voor instance of en typecasting
Je kan blijven muggenziften over die methode open() maar daar het hier helemaal niet om..

En je kan vijandig blijven reageren op iedereen die met een Beter alternatief komt maar ik denk dat jij hier degene bent die een nieuwe hobby moet zoeken.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

bronce schreef op woensdag 06 april 2011 @ 11:41:
Method overriding is een beter alternatief voor instance of en typecasting
Dat is jouw mening, maar door het dikgedrukt te maken maakt het niet ineens de waarheid. Probeer het eens met argumenten, dat werkt vaak beter om mensen te overtuigen.

open() is gewoon géén verantwoordelijkheid van een meubel, en hoort derhalve niet in de klasse Meubel. Door open() dan maar gewoon toe te voegen ben je imho fout bezig. De vraag die je jezelf beter kunt stellen is: waarom heb ik hier een collectie van generieke meubels, maar ben ik alleen geïnteresseerd in diegene die open kunnen? Gewoon maar open() toevoegen op Meubel omdat je het nodig denkt te hebben is symptoombestreiding.

Die vraag is natuurlijk niet te beantwoorden daar het om een gekunsteld voorbeeld gaat. Maar er zijn weldegelijk situaties waarin dit voor kan komen. De fout die hier gemaakt wordt is dat er gegeneraliseerd wordt. Puur het feit dat instanceof vaak een teken is van slechte code, impliceert niet meteen dat het altijd een teken is van slechte code. Sterker nog, als iedereen altijd fantastische code zou schrijven, dan zijn alle gevallen waarin instanceof gebruikt wordt per definitie juist.

Het visitor pattern zoals gepresenteerd door RayNbow is wel een mooi voorbeeld van een andere manier van symptoombestreiding - instanceof is "evil", dus werken we er maar omheen met een pattern, maar feitelijk is er niet veel veranderd, behalve dat je kunt zeggen "look, mom, I'm using patterns!". Die :+ smiley staat er niet voor niets. Wat overigens niet wegneemt dat het weldegelijk een mooi pattern is :), maar je zou in dit specifieke geval net zo goed instanceof kunnen gebruiken.

[ Voor 84% gewijzigd door .oisyn op 06-04-2011 12:09 ]

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.

En bovendien zie ik nog steeds geen reden om instanceof te mijden. De voorbeeldcode hierboven werkt vast ook maar persoonlijk vind ik hem een stukje onoverzichtelijker. Volgens mij is dit weer typisch zo'n persoonlijke voorkeur.

Oh, en jwoverg: zolang jouw auto's niet kunnen vliegen (zie mijn vorige post) was jouw voorlaatste post gewoon een ranzige oplossing. Ik zie je daar geen tegenargumenten voor bieden anders dan de dikgedrukte "jamaar het is gewoon zo!" in je laatste post. Zo werken discussies niet. :)

'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

Jeanpaul145 schreef op woensdag 06 april 2011 @ 02:27:

Al gedaan. Lees goed.

@PissedCapsLock: Kijk anders maar naar RayNBow's voorbeeld hieronder, dat is een goed voorbeeld van hoe je door objectoriëntatie toe te passen instanceofs kan vermijden.
Het zal wel aan mij liggen, maar ik let in het bijzonder op de " :+ " aan het einde.

Vind je dat nou écht beter dan gebruik maken van instanceof? Terwijl dat toch écht niet zo vreemd is in een objectgeörienteerde taal.
Ik vind het bijzonder vreemd en contraintuïtief dat in het voorbeeld van RayNBow er in het laatste stuk code buiten de klasse bekend moet zijn welke classes welke methoden implementeren. Voor elk soort class moet je daar code toevoegen terwijl dat met een interface Openable en een check via instanceof niet hoeft.
Wat denk je dat RayNBow zelf van zijn voorbeeld vindt? Waarom zou daar een " :+ " staan?

Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
NMe schreef op woensdag 06 april 2011 @ 11:55:
En bovendien zie ik nog steeds geen reden om instanceof te mijden.
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.

https://niels.nu


Acties:
  • 0 Henk 'm!

  • bronce
  • Registratie: Januari 2011
  • Laatst online: 16:17
Dus als jij word gevraagd om een programma voor Ikea te maken dat 1000en meubels bevat.
Ga jij dan in jou klasse met de collectie 1000X neer zitten instanceof lekker overzichtelijk.
En wat als een kast bestaat uit delen die geopend kunnen worden?

En natuurlijk kan je een auto proberen te laten vliegen waarom zou je het niet kunnen proberen?
Je kan net zo goed in methode maken open() die boolean returnt. en in Meubel zeggen dat hij false returnt en hem overriden in klassen die geopend moeten kunnen worden.

typecasting en instanceof worden gebruikt in hele specifieke gevallen bijvoorbeeld :
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class InstanceOf
{
    public static float divide(int a,int b)
    {
        return (float) a / b;
    }

    public static float divideFout(int a,int b)
    {
        return a/b;
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        System.out.println(divide(3,5));
        System.out.println(divideFout(3,5));
    }

}


output:
run:
0.6
0.0
BUILD SUCCESSFUL (total time: 1 second)

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

bronce schreef op woensdag 06 april 2011 @ 12:06:
Dus als jij word gevraagd om een programma voor Ikea te maken dat 1000en meubels bevat.
Ga jij dan in jou klasse met de collectie 1000X neer zitten instanceof lekker overzichtelijk.
Nee, 1 keer. Door ieder Meubel dat je open kunt doen Openable te laten implementeren.

Maar laten we de boel eens omdraaien. Jij zegt eigenlijk dat je iedere method die je ooit wilt implementeren in een class gewoon toe moet voegen aan Object. Immers, er is altijd wel een situatie te bedenken waar je gewoon een collectie hebt van objecten. En als je daaruit alle honden wilt laten blaffen, dan moet een Object dus ook een blaf() hebben. En een schenk(), voor alle theekannen die je wilt laten schenken. En een schiet(), voor alle wapens die je af wilt vuren. Ad infinitum.

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

bronce schreef op woensdag 06 april 2011 @ 12:06:
Dus als jij word gevraagd om een programma voor Ikea te maken dat 1000en meubels bevat.
Ga jij dan in jou klasse met de collectie 1000X neer zitten instanceof lekker overzichtelijk.
En wat als een kast bestaat uit delen die geopend kunnen worden?
instanceof <Interface hier> lijkt me in dat geval vrij handig, want het zou je niet moeten uitmaken welke meubels er zijn, het maakt voor een aanroep van een method alleen uit wat ze precies kunnen.

Als een kast bestaat uit delen, dan zijn die delen waarschijnlijk wel of niet Stackable, wel of niet Openable, etcetera. Welk deel iets wel en niet kan blijkt uit welke interfaces ze implementeren. In de uiteindelijke code maakt dat je alleen iets uit op het moment dat je iets wilt doen, dan check je met instanceof of ze de interface implementeren waarvan je de functionaliteit wilt checken.
En natuurlijk kan je een auto proberen te laten vliegen waarom zou je het niet kunnen proberen?
Je kan net zo goed in methode maken open() die boolean returnt. en in Meubel zeggen dat hij false returnt en hem overriden in klassen die geopend moeten kunnen worden.
Want dat is een ander fantastisch voorbeeld van hoe het niet moet in een hogere objectgeörienteerde programmeertaal...

Acties:
  • 0 Henk 'm!

  • majoh
  • Registratie: September 2001
  • Laatst online: 08:51

majoh

ᕦ(ò_óˇ)ᕤ

bronce schreef op woensdag 06 april 2011 @ 12:06:
Dus als jij word gevraagd om een programma voor Ikea te maken dat 1000en meubels bevat.
Ga jij dan in jou klasse met de collectie 1000X neer zitten instanceof lekker overzichtelijk.
En wat als een kast bestaat uit delen die geopend kunnen worden?
Met het maken van de interface Openable en daar de instanceof op doen, is er toch geen probleem?

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:06:
Dus als jij word gevraagd om een programma voor Ikea te maken dat 1000en meubels bevat.
Ga jij dan in jou klasse met de collectie 1000X neer zitten instanceof lekker overzichtelijk.
En wat als een kast bestaat uit delen die geopend kunnen worden?
Dat interesseert allemaal niet, want het type meubel boeit niet. Het feit dat ze de interface Openable implementeren wel. En dan is dat "1000x" ineens niet meer relevant.
En natuurlijk kan je een auto proberen te laten vliegen waarom zou je het niet kunnen proberen?
Je kan net zo goed in methode maken open() die boolean returnt. en in Meubel zeggen dat hij false returnt en hem overriden in klassen die geopend moeten kunnen worden.
Dat kun je doen, alleen heb je dan ranzige code geschreven. Well done. :)
typecasting en instanceof worden gebruikt in hele specifieke gevallen bijvoorbeeld :
Waarom noem je typecasting en instanceof in één zin? Beiden hebben specifieke toepassingen die helemaal niet per definitie aan elkaar gerelateerd zijn.

'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!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

bronce schreef op woensdag 06 april 2011 @ 12:06:
typecasting en instanceof worden gebruikt in hele specifieke gevallen bijvoorbeeld
Value typecasting heeft dan weer geen drol te maken met reference typecasting. In het eerste geval converteer je daadwerkelijk de waarde naar een ander type. In het tweede geval blijft het object gewoon intact, maar kijk je er op een andere manier tegenaan. Dat ze dezelfde syntax gebruiken is dan ook echt de enige gelijkenis.

[ Voor 32% gewijzigd door .oisyn op 06-04-2011 12:17 ]

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
Java:
1
2
3
4
public abstract class Meubel
{
     public abstract boolean IsOpenable();
}


Om nog even een knuppel in het hoenderhok te gooien :P

Acties:
  • 0 Henk 'm!

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

NMe

Quia Ego Sic Dico.

Vinnienerd schreef op woensdag 06 april 2011 @ 12:29:
Java:
1
2
3
4
public abstract class Meubel
{
     public abstract boolean IsOpenable();
}


Om nog even een knuppel in het hoenderhok te gooien :P
Voordat die ondanks de opmerking erna en de smiley erbij tóch serieus opgevat wordt als goed idee wijs ik graag nog even naar .oisyn's voorstel om dan alle functionaliteit die je ooit zou willen programmeren maar meteen aan Object te hangen. :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!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Java:
1
2
3
4
5
6
7
public class Object
{
    public abstract bool IsMeubel();
    public abstract bool IsOutputStream();
    public abstract bool IsString();
    // etc
}

Nee, dat is werkbaar ;)

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: 16:17
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
55
56
57
58
public abstract class Meubel
{
    public boolean open()
    {
        return false;
    }


}

public class Kast extends Meubel
{
    public boolean open()
    {
        return true;
    }

    public String toString()
    {
        return "Kast: Open: " + open();
    }
}
public class Bank extends Meubel
{
    public String toString()
    {
        return "Bank";
    }
}
public class Main
{
    private ArrayList<Meubel> meubels;

    public Main()
    {
        meubels = new ArrayList<Meubel>();
        meubels.add(new Bank());
        meubels.add(new Kast());
        meubels.add(new Kast());
        meubels.add(new Bank());
    }

    public void print()
    {
        for(Meubel m : meubels)
        {
            System.out.println(m.toString());
        }
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args)
    {
        new Main().print();
    }

}


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.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:22

.oisyn

Moderator Devschuur®

Demotivational Speaker

Maar waarom zit open() dan niet op de klasse Object?

De reden waarom jouw design van geen kanten klopt is omdat je de klasse Meubel aan gaat passen omdat je in main() een collectie hebt van Meubels waarbij je die meubels waarbij dat kan open wilt doen. Feitelijk bepaalt het gebruik van de klasse (iets waar de ontwerper van de klasse totaal geen controle over heeft) dus de verantwoordelijkheden van de klasse. Dat is absoluut niet hoe het werkt in OO, en resulteert in een totaal onwerkbare situatie, simpelweg omdat je niet alle klassen aan kan passen.

[ Voor 86% gewijzigd door .oisyn op 06-04-2011 12:37 ]

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.

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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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: 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
Pagina: 1 2 Laatste