[OOP] Beginnen - Wiskundig voorbeeld

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Top Low-Code Developer Gezocht!

Bedrijfsomschrijving Unieke Kansen, Uitstekende Arbeidsvoorwaarden & Inspirerend Team Wij zijn een toonaangevende, internationale organisatie die de toekomst van technologie vormgeeft door het creëren van innovatieve en baanbrekende oplossingen. Ons succes is gebaseerd op een hecht en gepassioneerd team van professionals die altijd streven naar het overtreffen van verwachtingen. Als jij deel wilt uitmaken van een dynamische, vooruitstrevende en inspirerende werkomgeving, dan is dit de perfecte kans voor jou! Functieomschrijving Als Low-Code Developer ben je een cruciaal onderdeel van ons team. Je werkt samen met collega's uit verschillende disciplines om geavanceerde applicaties te ontwikkelen en te optimaliseren met behulp van Low-code

Bekijk vacature »

 - Diov  -

- Diov -

27/09/2014 18:18:16
Quote Anchor link
Beste,

Ik heb een class Verzameling gemaakt, en daarna nog een class Verzamelingen.
De bedoeling is zoiets te maken als Venndiagrammen.

Dit is een klein projectje, enkel om van te leren.
Ben ik op de goeie weg met onderstaand voorbeeld?

Ik dacht er misschien aan om alles in 1 class te doen. Maar geef ik dan niet te veel verantwoordelijkheid aan die ene class?

Het is ook fein te weten dat je objecten mee kan geven als parameters. Dat wist ik niet (tot op vandaag).

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?php

class Verzameling
{
    private $elementen;
    
    function
__construct($elementen)
    {

        $this->elementen = $elementen;
    }

    
    public function getElementen()
    {

        return $this->elementen;
    }

    
    public function setElementen($elementen)
    {

        $this->elementen = $elementen;
    }

    
    public function controleerElement($element)
    {

        if(in_array($element, $this->elementen))
        {

            return true;
        }

        else
        {
            return false;
        }
    }
}


class Verzamelingen extends Verzameling
{
    private $verzamelingen, $unie, $doorsnede;
    
    function
__construct($verzamelingen)
    {

        $this->verzamelingen = $verzamelingen;
    }

    
    public function berekenUnie()
    {

        $this->unie = array();
        
        foreach($this->verzamelingen as $verzameling)
        {

            $this->unie = array_merge($this->unie, $this->LeesElementen($verzameling));
        }

        
        return array_unique($this->unie);
    }

    
    public function berekenDoorsnede()
    {

        $this->doorsnede = array();
        
        foreach($this->verzamelingen as $verzameling)
        {

            $this->doorsnede[] = $this->LeesElementen($verzameling);
        }
        
        
        return call_user_func_array('array_intersect',$this->doorsnede);
    }

    
    private function LeesElementen($verzameling)
    {

        return $verzameling->getElementen();
    }
}


$verzamelingA = new Verzameling(array(6));
$verzamelingB = new Verzameling(array(2,4,6,8));

$verzamelingen = new Verzamelingen(array($verzamelingA, $verzamelingB));

$unie = $verzamelingen->berekenUnie();
$doorsnede = $verzamelingen->berekenDoorsnede();

//var_dump($unie);
//var_dump($doorsnede);

?>



Met vriendelijke groeten,
Diov
Gewijzigd op 27/09/2014 18:18:37 door - Diov -
 
PHP hulp

PHP hulp

27/11/2024 05:21:45
 
Frank Nietbelangrijk

Frank Nietbelangrijk

27/09/2014 21:51:28
Quote Anchor link
Hoi Diov,

Ik vind het wel aardig alleen vraag ik me hier wel af waarom je een base class en een extended class aanmaakt.
Ik snap je argument over verantwoordelijkheden wel maar van de twee classes die je nu hebt kun je dezelfde verantwoordelijkheid noemen: het maken Venndiagrammen (zoals ik het nu bekijk).

In principe als je besluit om een base class te maken dan wil je die (in de toekomst) meerdere keren uitbreiden (extenden). Anders heeft het geen zin.

In een framework is de controller wel een goed voorbeeld.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?php
// classes/BaseController.php
class BaseController  // BASE CLASS
{
    private $template;

    function
__construct()
    {

        $this->template = new Template();
    }


    protected function loadView($template, $data = false)
    {

        $this->template->setData($data);
        return $this->template->Render();
    }
}


// controllers/ContactController.php
class ContactController extends BaseController // CONTROLLER VOOR HET CONTACTFORMULIER, UITBREIDING OP BASECONTROLLER
{
    public function indexAction()
    {

        $data = array(
            'name' => '',
            'email' => '',
            'subject' => '',
            'message' => ''
        );
        
        return $this->loadView('contactform', $data);
    }


    public function postAction()
    {

        $data = array(
            'name' => $_POST['name'],
            'email' => $_POST['email'],
            'subject' => $_POST['subject'],
            'message' => $_POST['message']
        );

        
        return $this->loadView('contactform', $data);
    }
}


// controllers/HomeController.php
class HomeController extends BaseController // CONTROLLER VOOR DE HOMEPAGE, UITBREIDING OP BASECONTROLLER
{
    public function indexAction()
    {

        return $this->loadView('homepage');
    }
}

?>


Toevoeging op 27/09/2014 22:03:08:

In jouw voorbeeld zou ik kiezen voor een class Circle en een class VennDiagram. Dit zijn dan twee totaal verschillende identiteiten dus ga je niet extenden. Wel gaat de class VennDiagram de class Circle meerdere keren gebruiken.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?php
class Circle
{
    private $offsetTop;
    private $offsetLeft;
    private $width;

    function
__construct($offsetTop, $offsetLeft, $width)
    {

        $this->offsetTop = $offsetTop;
        this->offsetLeft = $offsetLeft;
        this->width = $width;
    }

    
    // meer functies
}

class VennDiagram
{
    private $offsetTop;
    private $offsetLeft;
    private $circles; // array van het object Circle

    function __construct($offsetTop, $offsetLeft)
    {

        $this->offsetTop = $offsetTop;
        this->offsetLeft = $offsetLeft;
        this->circles = array();
    }

    
    public function addCircle($offsetTop, $offsetLeft, $width)
    {

        $this->circles[] = new Circle($offsetTop, $offsetLeft, $width);
    }


    // meer functies
}
?>
 
Wouter J

Wouter J

28/09/2014 00:38:05
Quote Anchor link
Er zijn 2 hele belangrijke dingen die je hier fout doet:
* "extends" geeft een IS_EEN relatie aan. Je moet de extends dus kunnen vervangen met IS_EEN. Bijv. PDO IS_EEN DatabaseAbstractionLayer. In jouw geval: Verzamelingen IS_EEN Verzameling. Dat klopt niet, een meervoud van iets kan nooit gelijk zijn aan het iets zelf.
* Als je extend erft de klasse die extend alle verantwoordelijkheden van zijn parent over. In dit geval heb je dus hetzelfde als dat je maar 1 klasse zou maken.

Wat ik me erg afvraag is of er hier uberhaupt wel spraken is van 2 verantwoordelijkheden.

Laten we beginnen met het primaire object in deze situatie: Set (ik raad aan altijd in het engels te werken). Deze Set klasse is een zogenaamde Value Object, het houdt een bepaalde waarde vast. Een kenmerk van een Value Object is dat hij immutable is: Je kan zijn data na het initialiseren niet meer aanpassen. Dat klopt ook in dit geval, wanneer een Set is aangemaakt kan hij niet meer worden aangepast. Ja, we kunnen hem "mergen" met een andere Set en zo een nieuwe Set maken, maar de vorige 2 Sets zijn dan niet aangepast. Onze Set klasse heeft dus geen setElements/addElements, slechts alleen een mogelijkheid om elementen in de constructor in te stellen en een getter om de elementen te verkrijgen:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
<?php
class Set
{
    private $elements;

    public function __construct(array $elements)
    {

        $this->elements = $elements;
    }


    public function getElements()
    {

        return $this->elements;
    }


    public function __toString()
    {

        return '{'.implode(', ', $this->getElements()).'}';
    }
}


$set = new Set([1, 2, 3]);

echo $set; // {1, 2, 3}
?>


Oke, dat is de basis. Nu kan deze Value Object ook nog wat logica omtrent de waarde die hij vasthoudt uitvoeren. Dat is geen aparte verantwoordelijkheid. Een aparte verantwoordelijkheid betekend dat je de klasse moet aanpassen om meer dan 1 rede. Op deze manier kunnen we dus een actie toevoegen waarbij we kijken of een waarde in een set voorkomt:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
class Set
{
    // ...

    public function contains($number)
    {

        return in_array($number, $this->elements);
    }
}


$set = new Set([1, 2, 3]);

$set->contains(2); // true
$set->contains(5); // false
?>


Ook kunnen we de 2 merge strategies voor een Set invoegen: union en intersection. Merk op dat we hierbij dus niet de huidige Set moeten aanpassen, deze is namelijk immutable. We moeten dus een nieuwe Set teruggeven met de waardes van beide sets.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
class Set
{
    // ...

    public function unite(Set $other)
    {

        return new Set(array_merge($this->getElements(), $other->getElements());
    }


    public function intersect(Set $other)
    {

        return new Set(array_intersect($this->getElements(), $other));
    }
}


$set1 = new Set([1, 2, 3]);
$set2 = new Set([3, 4, 5]);

echo $set1->unite($set2); // {1, 2, 3, 3, 4, 5}
echo $set1; // {1, 2, 3}
echo $set2->intersect($set1); // {3}
?>


Als laatste kunnen we bijv. nog iets maken dat 2 lijsten vergelijkt:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
class Set
{
    // ...

    public function equals(Set $other)
    {

        return array_unique($this->getElements()) === array_unique($other->getElements());
    }
}


$set1 = new Set([1, 2, 3]);
$set2 = $set1->unite($set1);

echo $set2; // {1, 2, 3, 1, 2, 3}

$set1->equals($set2); // true (dubbele waarden worden weggelaten)
?>


Al deze acties hebben te maken met Sets en mogen dus gewoon ondergebracht worden in de Set Value Object, zolang we maar zorgen dat we immutable blijven. Ga we echter Sets toepassen, dan behoort die actie niet meer tot een actie van de Set, maar een actie met de Set. Als ik bijv. wil kijken of een bepaalde Set echt de x waardes zijn voor een vergelijking als f(x) = 0 dan behoort deze actie niet meer tot de Set. Deze zou dan bijv. tot een FunctionSolver klasse behoren:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
class FunctionSolver
{
     public function isSetAnswer(callable $function, callable $equation, Set $set)
     {

         foreach ($set->getElements() as $element) {
             if (false === $equation($function($element))) {
                 return false;
             }
         }


         return true;
     }
}


$solver = new FunctionSolver();

$solver->isSetAnswer(
    function (
$x) { return pow($x, 2); }, // f(x) = x^2
    function ($y) { return $y == 4; },    // f(x) = 4
    new Set([-2, 2])
);
// true, f(-2) = 4 en f(2) = 4
?>
 
Frank Nietbelangrijk

Frank Nietbelangrijk

28/09/2014 12:33:59
Quote Anchor link
Zoals Wouter al eens heeft gezegd:

Het extenden van classes gebeurt veel minder vaak dan men vaak denkt. Eigenlijk als je net begint met OOP zou je heel dat woord 'extends' moeten vergeten.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.