Menu
Coddy logo textTech

Generator'lar ve Iterator'lar

Coddy'nin PHP Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 62 / 91.

Generator'lar, tam Iterator arayüzünü uygulamaya gerek kalmadan iterator'lar oluşturmak için basit bir yol sağlar. Bir generator fonksiyonu, değerleri teker teker üretmek için return yerine yield kullanır ve her değer arasında yürütmeyi duraklatır.

İşte bir sayı dizisi üreten temel bir generator:

<?php
function countTo(int $max): Generator {
    for ($i = 1; $i <= $max; $i++) {
        yield $i;
    }
}

foreach (countTo(3) as $number) {
    echo "$number\n";
}

Çıktı:

1
2
3

Temel avantaj bellek verimliliğidir. Bellekte tüm bir dizi oluşturmak yerine, generator'lar değerleri talep üzerine üretir. Bu, büyük veri kümeleriyle çalışırken çok önemlidir; bir milyon kaydı işleyen bir generator, on kaydı işleyenle aynı miktarda bellek kullanır.

Üreteçler ayrıca anahtar-değer çiftleri de üretebilir:

<?php
function userGenerator(): Generator {
    yield 'admin' => 'Alice';
    yield 'editor' => 'Bob';
}

foreach (userGenerator() as $role => $name) {
    echo "$role: $name\n";
}

Çıktı:

admin: Alice
editor: Bob

Kendi sınıflarınızı foreach ile yinelenebilir hale getirmek için Iterator arayüzünü uygulayın. Ancak çoğu durumda, üreteçler (generators) daha az hazır kod (boilerplate) ile daha temiz bir çözüm sunar. Bir sınıfın her şeyi aynı anda belleğe yüklemeden bir öğe koleksiyonunu sunması gerektiğinde, OOP'de özellikle yararlıdırlar.

challenge icon

Görev

Kolay

Her şeyi aynı anda belleğe yüklemeden büyük koleksiyonlar üzerinde verimli bir şekilde gezinmek için generator'ları kullanan bir ürün envanter sistemi oluşturalım. Ürünleri saklayan ve bunlar üzerinde farklı şekillerde gezinmek için generator metotları sağlayan bir sınıf oluşturacaksınız.

Kodunuzu üç dosya halinde düzenleyeceksiniz:

  • Product.php — Envanterdeki bir öğeyi temsil eden bir Product sınıfı oluşturun. Genel bir $sku (string), genel bir $name (string) ve genel bir $price (float) tanımlamak için constructor promotion kullanın.
  • Inventory.php — Bir ürün koleksiyonunu yöneten ve bunlar üzerinde gezinmek için generator metotları sağlayan bir Inventory sınıfı oluşturun. Product dosyasını dahil edin. Sınıf şunları yapmalıdır:
    • Ürünleri saklamak için özel (private) bir dizi özelliğine sahip olmalıdır
    • Koleksiyona bir ürün ekleyen bir addProduct(Product $product) metoduna sahip olmalıdır
    • Her bir ürünü teker teker döndüren (yield) bir allProducts(): Generator generator metoduna sahip olmalıdır
    • Yalnızca fiyatı verilen minimum fiyata eşit veya daha yüksek olan ürünleri döndüren, anahtarın SKU ve değerin ürün olduğu anahtar-değer çiftleri üreten bir expensiveProducts(float $minPrice): Generator generator metoduna sahip olmalıdır
  • main.php — Inventory dosyasını dahil edin. Bir girdi alacaksınız: bir minimum fiyat eşiği.

    Bir Inventory oluşturun ve şu üç ürünü ekleyin:

    • SKU: "A001", İsim: "Laptop", Fiyat: 999.99
    • SKU: "A002", İsim: "Mouse", Fiyat: 29.99
    • SKU: "A003", İsim: "Monitor", Fiyat: 349.99

    Önce, allProducts() üzerinde gezinin ve her ürünün adını kendi satırına yazdırın.

    Ardından boş bir satır yazdırın ve ardından girdi eşiğini kullanarak expensiveProducts() üzerinde gezinin. Her pahalı ürün için kendi satırına "[sku]: [name] - $[price]" yazdırın. Fiyatı tam olarak 2 ondalık basamakla biçimlendirin.

Bu görev, generator'ların koleksiyonlar üzerinde tembelce (lazily) gezinmenize nasıl olanak tanıdığını gösterir — her ürün yalnızca istendiğinde üretilir, bu da bu yaklaşımı büyük envanterler için bellek açısından verimli hale getirir. expensiveProducts() içindeki anahtar-değer üretimi, generator'ların yapılandırılmış yineleme verilerini nasıl sağlayabileceğini gösterir.

Kopya kağıdı

Üreteçler (Generators), return yerine yield kullanarak yineleyiciler (iterators) oluşturmanın bellek açısından verimli bir yolunu sunar. Değerleri her seferinde bir tane üretirler ve her değer arasında yürütmeyi duraklatırlar.

Temel üreteç fonksiyonu:

<?php
function countTo(int $max): Generator {
    for ($i = 1; $i <= $max; $i++) {
        yield $i;
    }
}

foreach (countTo(3) as $number) {
    echo "$number\n";
}

Üreteçler anahtar-değer çiftleri üretebilir:

<?php
function userGenerator(): Generator {
    yield 'admin' => 'Alice';
    yield 'editor' => 'Bob';
}

foreach (userGenerator() as $role => $name) {
    echo "$role: $name\n";
}

Ana avantaj bellek verimliliğidir - üreteçler, tüm dizileri bellekte oluşturmak yerine değerleri talep üzerine üretirler. Bu, özellikle OOP bağlamlarında büyük veri kümeleri veya koleksiyonlarla çalışırken kullanışlıdır.

Kendin dene

<?php

require_once 'Inventory.php';

// Girdiyi oku
$minPrice = floatval(trim(fgets(STDIN)));

// TODO: Bir Inventory örneği oluşturun

// TODO: Üç ürün ekleyin:
// SKU: "A001", Name: "Laptop", Price: 999.99
// SKU: "A002", Name: "Mouse", Price: 29.99
// SKU: "A003", Name: "Monitor", Price: 349.99

// TODO: allProducts() üzerinde dönün ve her ürünün adını yazdırın

// TODO: Boş bir satır yazdırın

// TODO: $minPrice kullanarak expensiveProducts() üzerinde dönün
// Her pahalı ürün için "[sku]: [name] - $[price]" yazdırın
// Fiyatı tam olarak 2 ondalık basamakla formatlayın

?>
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler