Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

31

05.02.2017, 14:42

Was ich daran nicht verstehe ist, was Dir das jetzt für

Quellcode

1
new AndCondition(new HasAge(18), new OrCondition(new HasFur(), new HasCar())->fulfills($creature)
bringt. Würdest Du dann sowas machen?

Quellcode

1
2
3
$creature->fulfills(function (Animal $animal): bool {
  return new AndCondition(new HasAge(18), new OrCondition(new HasFur(), new HasCar())->fulfills($animal);
});

Das würde dann doch total unschön eine Exception schmeißen, weil HasCar nichts mit einem Animal anfangen kann. Du müsstest also in HasCar eigentlich doch wieder mit instanceof arbeiten. Das Typsystem von PHP gibt es einfach nicht anders her. Alternativ müsstest Du pro Subtyp eigene Or und AndCondition bauen, das ist aber auch nicht toll...

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Chromanoid« (05.02.2017, 14:58)


Architekt

Community-Fossil

  • »Architekt« ist der Autor dieses Themas

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

32

05.02.2017, 14:56

Ich würde in der konkreten Bedingung die $creature per Lambda abfragen, ob das Lambda erfüllt wird. Wenn der Typ des Lambdas nicht passt (Human <=> Animal) dann generiert PHP einen Type-Error. Ob PHP jetzt den Error generiert oder ich mit instanceof abfrage und ggf. 'ne Exception werfe ist doch egal, oder nicht?
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

33

05.02.2017, 15:00

Mmh dann kannst Du Dir die Typisierung auch einfach sparen und die Methoden abfragen, ob sie da sind oder nicht... Gibt genauso Fehler.

Ich würde eher mit instanceof prüfen, bei der falschen Kreatur false zurückgeben und keine Exception werfen.

Findest Du die Lösung so wirklich so schlimm?

Quellcode

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
interface Creature
{
    public function isAlive(): bool;
}

interface Human extends Creature
{
    public function hasCar():bool;
}

interface Animal extends Creature
{
    public function hasFur(): bool;
    public function isHibernating():bool;
}

interface Condition
{
    public function isFulfilledBy($target): bool;
}

class HasCar implements Condition {
    public function isFulfilledBy($target): bool {
        return $target instanceof Human && $target->hasCar();
    }
}

class IsAlive implements Condition {
    public function isFulfilledBy($target): bool {
        return $target instanceof Creature && $target->isAlive();
    }
}

class And implements Condition {
    $condition1=null;
    $condition2=null;

    function __construct(Condition $condition1, Condition $condition2) {
        $this->condition1= $condition1;
        $this->condition2= $condition2;
    }

    public function isFulfilledBy($target): bool {
       return $condition1->isFulfilledBy($target) && $condition2->isFulfilledBy($target);
    }
}

new And( new IsAlive(), new HasCar() )->isFulfilledBy($target)

So hast Du eine ziemlich erweiterbare generische Lösung.

Architekt

Community-Fossil

  • »Architekt« ist der Autor dieses Themas

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

34

05.02.2017, 15:11

So ganz ohne Type-Hints find' ich es schon übel um ehrlich zu sein. :)
Was echt schön wäre, wäre die Möglichkeit, das interface nachträglich restriktiver zu machen. Also aus

Quellcode

1
2
3
4
interface CreatureInterface
{
    public function fulfills(ConditionInterface $condition): bool;
}


das hier zu machen:

Quellcode

1
2
3
4
interface HumanInterface extends CreatureInterface
{
    public function fulfills(HumanConditionInterface $condition): bool;
}


oder um den anderen Weg zu gehen, aus

Quellcode

1
2
3
4
interface ConditionInterface
{
    public function fulfills(Creature $creature): bool;
}



das hier machen zu können

Quellcode

1
2
3
4
interface HumanConditionInterface extends ConditionInterface
{
    public function fulfills(Human $human): bool;
}


Da Human das Creature interface implementiert, wäre das interface der HumanCondition lediglich restriktiver, aber in gewisser Weise ja immer noch erfüllt. Aber ich glaub es gibt keine Sprache die das erlaubt, oder irre ich mich da?
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

35

05.02.2017, 15:13

Ne, das wäre ja auch schrecklich, durch das restriktiver machen würde die Interface-Erweiterung nicht mehr das Interface erfüllen.

Architekt

Community-Fossil

  • »Architekt« ist der Autor dieses Themas

Beiträge: 2 481

Wohnort: Hamburg

Beruf: Student

  • Private Nachricht senden

36

05.02.2017, 15:16

Ich fänd' es in diesem Fall sehr angenehm muss ich sagen. :) Wir überschreiben den Vertrag und machen ihn restriktiver. Minimal Beispiel:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php

interface Z
{
    
}

interface Y extends Z
{
    
}

interface A
{
    public function test(Z $z);
}

interface B extends A
{
    public function test(Y $y);
}


A akzeptiert Z & Y aber B nur noch Y, kein Z. Das ist doch eig. ein nettes Feature (wenn es denn ginge).

Edit: Mir fällt auf (bin whs. zulang in PHP die letzten Wochen): In anderen Sprache wie C#, Java etc. geht das natürlich, weil wir eine weitere Methode hinzufügen, aber nicht die ursprüngliche überschreiben / restriktiver machen.
Der einfachste Weg eine Kopie zu entfernen ist sie zu löschen.
- Stephan Schmidt -

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »Architekt« (05.02.2017, 15:22)


37

05.02.2017, 17:28

Ja, man macht es nicht restriktiver, sondern man baut eine Falle in die API/Bedienung ein ^^.

bImpl.test( (Z) yImpl ) vs. bImpl.test( yImpl ) vs. ((A) bImpl).test( yImpl )

urks

Werbeanzeige