Menu
CoddyTech

Wildcard (?, extends, super)

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Java di Coddy. Pelajaran 57 dari 87.

Parameter tipe berbatas membatasi generics ke tipe tertentu, tetapi bagaimana jika kamu bekerja dengan tipe generik yang sudah ada dan tidak tahu, atau tidak peduli dengan, parameter tipe yang tepat? Di sinilah wildcard berperan.

Wildcard tak terbatas ? mewakili tipe yang tidak diketahui. Ini berguna saat kamu ingin menerima tipe berparameter apa pun:

public static void printList(List<?> list) {
    for (Object item : list) {
        System.out.println(item);
    }
}

printList(new ArrayList<String>());   // Berfungsi
printList(new ArrayList<Integer>());  // Berfungsi

Wildcard berbatas atas ? extends Type menerima tipe yang ditentukan atau subclass apa pun darinya. Gunakan ini saat kamu perlu membaca dari struktur generik:

public static double sumNumbers(List<? extends Number> numbers) {
    double sum = 0;
    for (Number n : numbers) {
        sum += n.doubleValue();
    }
    return sum;
}

sumNumbers(Arrays.asList(1, 2, 3));        // list berisi Integer
sumNumbers(Arrays.asList(1.5, 2.5));       // list berisi Double

Wildcard berbatas bawah ? super Type menerima tipe yang ditentukan atau superclass apa pun darinya. Gunakan ini saat kamu perlu menulis ke struktur generik:

public static void addIntegers(List<? super Integer> list) {
    list.add(1);
    list.add(2);
}

List<Number> numbers = new ArrayList<>();
addIntegers(numbers);  // Berhasil, Number adalah supertipe dari Integer

Panduan yang berguna: gunakan extends saat kamu hanya membaca (produsen), gunakan super saat kamu hanya menulis (konsumen). Ini dikenal sebagai prinsip PECS: Producer Extends, Consumer Super.

challenge icon

Tantangan

Mudah

Mari kita bangun sistem pemberian makan di kebun binatang yang menunjukkan ketiga jenis wildcard! Kamu akan membuat hierarki hewan dan makanan, lalu menulis beberapa method utilitas yang menggunakan wildcard tanpa batas, batas atas, dan batas bawah untuk menangani berbagai skenario pemberian makan.

Kamu akan mengatur kodemu dalam empat file:

  • Food.java: Buat hierarki class sederhana untuk makanan. Mulailah dengan class dasar Food yang memiliki field privat name (String), constructor untuk menginisialisasinya, dan method getName(). Lalu buat dua subclass dalam file yang sama: Meat extends Food (constructor memanggil super(name)) dan Vegetable extends Food (pola yang sama).
  • Animal.java: Buat class dasar Animal dengan field privat species (String), constructor, dan method getSpecies(). Buat dua subclass: Carnivore dan Herbivore, masing-masing extends Animal dan memanggil constructor induknya.
  • ZooFeeder.java: Di sinilah wildcard menunjukkan kegunaannya! Buat class utilitas dengan tiga method statis:

    printInventory(List<?> items) - Menggunakan wildcard tanpa batas untuk mencetak list apa pun. Lakukan perulangan dan cetak setiap item menggunakan toString(), satu item per baris.

    calculateTotalFood(List<? extends Food> foods) - Menggunakan wildcard dengan batas atas untuk membaca dari list dengan tipe Food apa pun. Kembalikan jumlah item sebagai int. Ini menunjukkan cara membaca dari produsen.

    addMeatToStock(List<? super Meat> stock, String meatName) - Menggunakan wildcard dengan batas bawah untuk menulis ke list yang dapat menampung Meat. Buat object Meat baru dengan nama yang diberikan, lalu tambahkan ke persediaan. Ini menunjukkan cara menulis ke konsumen.

  • Main.java: Satukan sistem pemberian makan di kebun binatangmu! Kamu akan menerima dua input: nama daging (String) dan nama sayuran (String).

    Pertama, buat ArrayList<Food> dan tambahkan object Meat dengan nama daging serta object Vegetable dengan nama sayuran. Cetak Food inventory:, lalu panggil printInventory dengan list ini.

    Berikutnya, cetak satu baris kosong, lalu cetak Total food items: [count] menggunakan calculateTotalFood pada list makananmu.

    Terakhir, buat ArrayList<Food> baru bernama meatStock. Cetak satu baris kosong, lalu Adding to meat stock.... Panggil addMeatToStock dengan list ini dan string "Beef". Lalu cetak Meat stock after adding: dan panggil printInventory pada persediaan daging.

Kamu akan menerima dua input secara berurutan: nama daging dan nama sayuran.

Override toString() di class Food-mu agar mengembalikan nama makanan, sehingga pencetakan berfungsi dengan benar. Perhatikan bagaimana setiap jenis wildcard memiliki tujuan yang berbeda: ? untuk fleksibilitas maksimal saat kamu hanya perlu membaca sebagai Object, ? extends saat membaca tipe tertentu, dan ? super saat menulis ke koleksi!

Coba sendiri

import java.util.Scanner;
import java.util.ArrayList;
import java.util.List;

class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String meatName = scanner.nextLine();
        String vegetableName = scanner.nextLine();
        
        // TODO: Buat ArrayList<Food> dan tambahkan object Meat dan Vegetable
        
        // TODO: Cetak "Food inventory:", lalu panggil printInventory
        
        // TODO: Cetak baris kosong, lalu "Total food items: [count]" menggunakan calculateTotalFood
        
        // TODO: Buat ArrayList<Food> baru bernama meatStock
        
        // TODO: Cetak baris kosong, lalu "Adding to meat stock..."
        
        // TODO: Panggil addMeatToStock dengan meatStock dan "Beef"
        
        // TODO: Cetak "Meat stock after adding:", lalu panggil printInventory pada meatStock
    }
}
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler Java online