Inkrementacja wartości na obiekcie w PHP

0

Taki kod inkrementujący atrybut w klasie

 class Integer
{
  protected $_value;
  
  public function __construct($value)
  {
     $this->_value = (int)$value;
  } 
  
  
  public function zwieksz()
  {
     return (int)$this->_value += 1;
     
  }

  public function __toString()
  {
     return (int)$this->_value;
  }
}


$int0 = new Integer(0);
$int0->zwieksz();
echo $int0->zwieksz();

Jak zmienić ciało klasy, żeby można było inkrementować na tym samym obiekcie w łańcuchu wywołań?

$int0 = new Integer(0);
echo $int0->zwieksz()->zwieksz();

Programuje już troche w php, ale nie wiem i w ogóle nie widze sensu takiego łańcuchowego kombinowania...

1

Do wywołania metody potrzebujesz obiektu, na rzecz którego wywołasz tą metodę, np. $int0->zwieksz(). Zastanów się, co w tym momencie zwraca Twoja metodazwieksz oraz co powinna zwracać, żeby takie wywołanie, zwane method chaining, było możliwe.

Programuje już troche w php, ale nie wiem i w ogóle nie widze sensu takiego łańcuchowego kombinowania...

Odp brzmi:

The point is - in 99% cases you can probably do just as well or even better without method chaining. But there is the 1% where this is the best approach.

Method chaining - why is it a good practice, or not?

1

To ze swojej strony polecę jeszcze ten artykuł https://ocramius.github.io/blog/fluent-interfaces-are-evil/

0

Nie mam nic przeciwko chaining methods, ale pytałem o proste przekształcenie ciała klasy tak, żeby śmieszną inkrementacje można było zapisać w jednej linii poprzez wywołanie metody dwukrotnie, albo wielokrotnie w łańcuchu na tym samym obiekcie. Rozumiem,że osoby, które udzieliły odpowiedzi, wiedzą jak zmienić ciało klasy, ale chcą, żebym doszedł do tego sam..? Nie wiem ile lat trzeba programować w php,żeby zrobić to w kilka minut, ale jeśli trzeba kilku lat, to najwyrażniej nie ma na tym forum programistów, którzy zmieniliby ciało tej klasy w kilka minut...

0

Wytłumaczyli Ci jak to zrobić. Jeżeli tego nie zrozumiałeś oznacza to, że nie nadajesz się na programistę. Co więcej sam wytłumaczyłeś w swoim pytaniu jak to zrobić ale dalej nie wiesz jak.

0

ok, chyba odpowidz @axelbest jest pomocna, ale potrzebny jest inteface, a w tym problemie nie było mowy o dziedziczeniu po interface..ok..dzieki

0

Taki kod:

$int0 = new Integer(0);
echo $int0->zwieksz()->zwieksz();

jest bez sensu, bo żeby zadziałał musiałby być jakiś magiczny polimorfizm zwracanych wartości. Albo zwracasz intancję obiektu na której możesz wywołać metodę "zwiększ" albo wartość inkrementowanej wartości. Mówiąc prościej: fluent API to prosta sztuczka, w której z metody zwracasz instację ($this).

0

Inkrementacja na obiekcie w łańcuchu wymaga, żeby metoda zwieksz() zwracała obiekt, a nie atrybut.

 <?php

class Integer
{
  protected $_value;
  
  public function __construct($value)
  {
     $this->_value = (int)$value;
  } 
  
  
  public function zwieksz()
  {
     return new Integer($this->_value += 1);
     
  }

  public function getValue()
  {
     return $this->_value;
  }

  
}


$int0 = new Integer(0);
echo $int0->zwieksz()->zwieksz()->zwieksz()->getValue();

?>

Dzięki za pomoc. Temat do zamknięcia.

0

O nie. To jest jedno z możliwych podejść:

class Integer
{
    private $_value;
    
    public static function factory($value = 0)
    {
        return new Integer($value);
    }
 
    public function __construct($value = 0)
    {
        $this->_value = $value;
    } 
 
    public function increment($number = 1)
    {
        $this->_value += $number;
        return $this;
    }
 
    public function value()
    {
        return (int) $this->_value;
    }

    public function __toString()
    {
        return (string) $this->_value;
    }
}

$result = Integer::factory(0)
    ->increment(1)
    ->increment(2)
    ->increment(-5);
 
echo ($result);

I nie żadne rzutowanie na int w metodzie __toString tylko na string bo inaczej wyrzuci fatal error. W powyższym przykładzie metoda factory jest po to, żeby to wszystko obsłużyć tak jak tu jest. Są dwie opcje:

$int = new Integer(0);
$int->increment(1);
$int->increment(2);
$result = $int; 

echo $result;
//
var_dump($result->value());

albo:

$result = Integer::factory(0)
    ->increment(1)
    ->increment(2);

echo $result;
//
var_dump($result->value()); 
0
 <?php

class Integer
{
  protected $_value;
  
  public function __construct($value)
  {
     $this->_value = (int)$value;
  } 
  
  
  public function zwieksz()
  {
     return new Integer($this->_value += 1);
     
  }

  public function __toString()
  {
     return (string)$this->_value;
  }

  
}


$int0 = new Integer(0);
echo $int0->zwieksz()->zwieksz();

?>

ale można jeszcze bez tworzenia nowego obiektu...


public function zwieksz() {
    $this->_value++;
    return $this;
}
0

@axelbest: Ile lat w php i czy na pewno jestes najlepszy w Wawie. Startuje na programiste PHP. Mam już umówionych klika spotkań, zadania rekrutacyjne. Jak wygląda popyt w Wawie na programistów php? To zadanie zawaliłem online, ale w końcu znalazłem właściwe rozwiązanie..;)

0
Ja nawet nie jestem średni.... a co dopiero mierzyć miarą najlepszego... :) A popyt jest spory. A skoro dopiero zaczynasz to może gdzieś na juniora się załapiesz. Btw. tak jak wielu innym anonimom, polecam założenie konta :)
 

Aplikowałem na oferty bez "Junior" w nazwie i jest jakiś odzew, bo mam troche w CV i w sumie nie jestem zupełnie początkujący, ale trafiłem na rekruterów, którzy chcą wszystkim kandydatom udowadniać, że nic nie potrafią...no i praca całkowicie zdalna...heh..zawsze to jakieś doświadczenie.

0

ale trafiłem na rekruterów, którzy chcą wszystkim kandydatom udowadniać, że nic nie potrafią

Jak by nie patrzeć - to Ty masz udowodnić firmie, że się nadajesz i jesteś de best. Jeśli rekruter jest Cię w stanie zagiąć na czymś, co nie wymaga zaglądania do kodu źródłowego VMki PHP, prawdopodobnie akurat w tej firmie byś się za bardzo mógł nie przydać ;-)

0
 Jak by nie patrzeć - to Ty masz udowodnić firmie, że się nadajesz i jesteś de best. Jeśli rekruter jest Cię w stanie zagiąć na czymś, co nie wymaga zaglądania do kodu źródłowego VMki PHP, prawdopodobnie akurat w tej firmie byś się za bardzo mógł nie przydać ;-)

Nie twierdze ze wiem wszystko, ale juz po 10 min. rozmowy wiedzialem, że nie chce pracowac dla tych aroganckich januszów i to zdalnie pod 8-godzinnym nadzorem. Wspolczuje tym co tak pracuja..;)

0

Ta statyczna metoda factory i te chain methods są o tyle fajne że mogą posłużyć do takich zabaw:

abstract class Number
{
    protected $_value;

    public static function factory($model, $value = 0)
    {
        $class = 'Number' . ucfirst($model);
        return new $class($value);
    }

    public function increment($number = 1)
    {
        $this->_value += $number;
        return $this;
    }

    public function __construct($value = 0)
    {
        $this->_value = $value;
    }

    abstract public function value();
    abstract public function __toString();
}

class NumberInteger extends Number
{
    private $_as_hex = FALSE;
    private $_fix = NULL;

    public function as_hex($fix = NULL)
    {
        $this->_as_hex = TRUE;
        $this->_fix = $fix;
        return $this;
    }

    public function value()
    {
        return (int) $this->_value;
    }

    public function __toString()
    {
        if ($this->_as_hex === TRUE)
        {
            return ($this->_fix !== NULL)
                ? sprintf('%0' . $this->_fix . 'x', $this->_value)
                : dechex($this->_value);
        }
        return (string) $this->_value;
    }
}

class NumberDecimal extends Number
{
    public static $decimals = 6;

    public function value()
    {
        return number_format($this->_value, self::$decimals, '.', '');
    }

    public function __toString()
    {
        return $this->value();
    }
}

// test

// Integer values
$integer1 = Number::factory('Integer', 301)
    ->as_hex(4)
    ->increment(2);
$integer2 = Number::factory('Integer', 521)
    ->as_hex()
    ->increment(1);
$integer3 = Number::factory('Integer', 122)
    ->increment(122);

// Decimal values
NumberDecimal::$decimals = 4;
$decimal1 = Number::factory('Decimal', 20)
    ->increment(5.0001);
$decimal2 = Number::factory('Decimal', 1)
    ->increment(1);
$decimal3 = Number::factory('Decimal', $decimal1->value())
    ->increment($decimal2->value());

echo "Integer1: " . $integer1;
echo "\n";
echo "Integer2: " . $integer2;
echo "\n";
echo "Integer3: " . $integer3;
echo "\n";
echo "Decimal1: " . $decimal1;
echo "\n";
echo "Decimal2: " . $decimal2;
echo "\n";
echo "Decimal3: " . $decimal3;

wynik:

Integer1: 012f
Integer2: 20a
Integer3: 244
Decimal1: 25.0001
Decimal2: 2.0000
Decimal3: 27.0001

W tym założeniu jest ten prefix klas czyli klasy rozszerzające klasę abstrakcyjną muszą się nazywać odpowiednio: NumberInteger, NumberDecimal, NumberFloat itd..., choć oczywiście można przyjąć inne podejście. Uczestniczyłem kiedyś w procesie rekrutacji i byłem na rozmowie na stanowisko Junior PHP, to nie jest taka prosta sprawa, wydaje mi się że jest to na zasadzie podoba się/*nie podoba się, wynik był odmowny, nie wiem kogo właściwie szukali. Powyższe podejście i styl nazewnictwa są stosowane w niektórych frameworkach, tych mniej popularnych, nie działam w Symfony (z tym była związana rekrutacja). Stąd też wątpliwe żeby chodziło tylko o kompetencje w samym czystym PHP.

0

@drorat1: Bawić się zawsze można, a nawet trzeba. Ja byłem na kilku rozmowach i też mam preferencje, jesli chodzi o pracodawce. To nie jest tak, że chcę pracować byle gdzie, byle pracować. Ja też na rozmowie często dochodze do wniosku, że rekruter, to kretyn, a to o co pyta i czego niby nie wiem, nijak się ma do moich umiejętności programistycznych i zdolności przetwarzania informacji. Też bliżej mi do 40-stki. ;)

0

Dobrze Was tak poczytać o przygodach z pracą programisty, mnie trzyma umowa w obecnej firmie, gdzie tylko klepie selecty w sqlu, a programowanie w większości tylko po pracy. Z drugiej strony myśl o takiej rozmowie staje się coraz bardziej przerażająca bo im więcej umiem, tym mam większą świadomość jak wiele jeszcze mi tej wiedzy brakuje :P
Chociaż mi się akurat podoba robienie wszystkiego. Fajnie napisac jakiś zgrabny backen w Laravel, a później wymyślić ciekawy i łopatologiczny interfejs . Nie wiem czy potrafiłbym skupić się tylko na backendzie, albo froncie (z forntu mam na myśli JSy z Vue na czele, a nie tworzenie grafiki) u jakiegoś Janusza, więc powoli staram się coś własnego rozkręcić.

Co do wątku to również nie rozumiem po co tak kombinować z chainowaniem, lepiej napisac funkcję przyjująca opcjonalne parametry i pisać wtedy ->increments(2) zamiast chainowac tą samą metodę tak jak podał przykład drorat1.

1 użytkowników online, w tym zalogowanych: 0, gości: 1