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 mengetahui, atau tidak peduli dengan, parameter tipe yang tepat? Di sinilah wildcard berperan.

Wildcard tak berbatas ? 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 salah satu subclass-nya. 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 mana 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);  // Berfungsi, Number adalah supertipe dari Integer

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

challenge icon

Tantangan

Mudah

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

Kamu akan menyusun kodemu dalam empat file:

  • Food.java: Buat hierarki class sederhana untuk makanan. Mulai dengan class dasar Food yang memiliki field privat name (String), constructor untuk menginisialisasinya, dan method getName(). Lalu buat dua subclass di file yang sama: Meat extends Food (constructor memanggil super(name)) dan Vegetable extends Food (dengan 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 berperan! Buat class utilitas dengan tiga method statis:

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

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

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

  • Main.java: Satukan sistem pemberian pakan 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 stok 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 berbeda: ? untuk fleksibilitas maksimal saat kamu hanya perlu membaca sebagai Object, ? extends saat membaca tipe tertentu, dan ? super saat menulis ke collection!

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 untuk 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