Nama : Erlangga Rizqi Dwi Raswanto
NRP : 5025241179
Kelas : PBO A
Pada pertemuan ke-13, materi yang dibahas adalah abstract class dalam pemrograman berorientasi objek (OOP) menggunakan Java. Abstract class berada pada posisi cukup tinggi dalam hierarki kelas dan berfungsi sebagai blueprint bagi kelas turunannya.
Ciri utama abstract class:
-
Tidak dapat di-
new(tidak bisa dibuat objek langsung). -
Dapat berisi:
-
method konkret (punya body/isi),
-
method abstrak (hanya deklarasi, tanpa body).
-
-
Subclass wajib mengimplementasikan semua method abstrak, jika tidak maka subclass tersebut juga harus dideklarasikan sebagai abstract.
Pada laporan ini, implementasi abstract class ditunjukkan melalui dua latihan:
-
Abstract class MakhlukHidup yang diturunkan ke Manusia, Hewan, dan Tumbuhan.
-
Simulasi sederhana Foxes and Rabbits yang diubah agar menggunakan abstract class Animal.
-
Abstract class: kelas yang tidak bisa diinstansiasi secara langsung dan biasanya berperan sebagai kerangka umum.
-
Abstract method: method yang hanya memiliki signature tanpa implementasi. Implementasinya dipaksa dilakukan di subclass.
-
Abstract class cocok dipakai ketika:
-
Ada perilaku umum yang bisa disediakan bentuk default (method konkret).
-
Ada perilaku khusus yang harus berbeda di tiap subclass (method abstrak).
-
-
Abstract class sangat berhubungan dengan:
-
Inheritance (pewarisan)
-
Polymorphism (satu referensi parent bisa menyimpan berbagai objek subclass dan memanggil method yang sesuai jenis objeknya).
-
Latihan 1 – Abstract Class Makhluk Hidup
3.1 Deskripsi Program
Pada latihan ini dibuat sebuah hirarki kelas:
-
MakhlukHidup→ abstract class sebagai induk. -
Manusia,Hewan,Tumbuhan→ kelas turunan yang mengimplementasikan cara bernapas dan bergerak masing-masing.
Konsep yang digunakan:
-
Abstraksi: Makhluk hidup secara umum punya nama, bisa bernapas, dan bergerak, tetapi cara bernapas & bergeraknya berbeda.
-
Inheritance: Manusia, Hewan, dan Tumbuhan mewarisi struktur dasar dari MakhlukHidup.
-
Polymorphism: Objek disimpan dalam tipe
MakhlukHiduptetapi saat method dipanggil, implementasi yang dieksekusi sesuai tipe konkret (Manusia/Hewan/Tumbuhan).
3.2 Kode Program Latihan 1
3.2.1 MakhlukHidup.java
public abstract class MakhlukHidup {
protected String nama;
public MakhlukHidup(String nama) {
this.nama = nama;
}
// Method abstrak: wajib diimplementasikan subclass
public abstract void bernapas();
public abstract void bergerak();
// Method konkret: berlaku umum untuk semua makhluk hidup
public void info() {
System.out.println("Nama: " + nama);
}
}
3.2.2 Manusia.java
public class Manusia extends MakhlukHidup {
private String pekerjaan;
public Manusia(String nama, String pekerjaan) {
super(nama);
this.pekerjaan = pekerjaan;
}
@Override
public void bernapas() {
System.out.println(nama + " bernapas menggunakan paru-paru.");
}
@Override
public void bergerak() {
System.out.println(nama + " berjalan menggunakan kaki.");
}
@Override
public void info() {
super.info();
System.out.println("Pekerjaan: " + pekerjaan);
}
}
3.2.3 Hewan.java
public class Hewan extends MakhlukHidup {
private String jenisHewan;
public Hewan(String nama, String jenisHewan) {
super(nama);
this.jenisHewan = jenisHewan;
}
@Override
public void bernapas() {
System.out.println(nama + " bernapas menggunakan paru-paru atau insang (sesuai jenis).");
}
@Override
public void bergerak() {
System.out.println(nama + " bergerak dengan cara khas hewan " + jenisHewan + ".");
}
@Override
public void info() {
super.info();
System.out.println("Jenis Hewan: " + jenisHewan);
}
}
3.2.4 Tumbuhan.java
public class Tumbuhan extends MakhlukHidup {
private String jenisTumbuhan;
public Tumbuhan(String nama, String jenisTumbuhan) {
super(nama);
this.jenisTumbuhan = jenisTumbuhan;
}
@Override
public void bernapas() {
System.out.println(nama + " bernapas melalui proses fotosintesis dan respirasi sel.");
}
@Override
public void bergerak() {
System.out.println(nama + " tidak bergerak aktif, tetapi tumbuh dan mengikuti arah cahaya.");
}
@Override
public void info() {
super.info();
System.out.println("Jenis Tumbuhan: " + jenisTumbuhan);
}
}
3.2.5 MainMakhlukHidup.java
public class MainMakhlukHidup {
public static void main(String[] args) {
MakhlukHidup manusia = new Manusia("Andi", "Programmer");
MakhlukHidup hewan = new Hewan("Kucing", "Mamalia");
MakhlukHidup tumbuhan = new Tumbuhan("Mangga", "Pohon Buah");
System.out.println("=== Informasi Makhluk Hidup ===");
System.out.println("\n-- Manusia --");
manusia.info();
manusia.bernapas();
manusia.bergerak();
System.out.println("\n-- Hewan --");
hewan.info();
hewan.bernapas();
hewan.bergerak();
System.out.println("\n-- Tumbuhan --");
tumbuhan.info();
tumbuhan.bernapas();
tumbuhan.bergerak();
}
}
3.3 Penjelasan Konsep OOP pada Latihan 1
-
Abstract Class & Method
-
MakhlukHidupdideklarasikanabstract. -
bernapas()danbergerak()adalah method abstrak → tidak punya body di superclass, dipaksa diimplementasikan olehManusia,Hewan,Tumbuhan.
-
-
Inheritance
-
Manusia extends MakhlukHidup -
Hewan extends MakhlukHidup -
Tumbuhan extends MakhlukHidup
Ketiga kelas turunan otomatis punya atributnamadan methodinfo().
-
-
Polymorphism
-
Di
MainMakhlukHidup, variabel bertipeMakhlukHidupbisa menyimpan objekManusia,Hewan, danTumbuhan. -
Pemanggilan
manusia.bernapas(),hewan.bernapas(), dll, akan mengeksekusi implementasi sesuai objek konkret.
-
4. Latihan 2 – Abstract Class pada Simulasi Foxes and Rabbits
4.1 Deskripsi Program
Latihan kedua menggunakan contoh simulasi dari buku: Foxes and Rabbits. Ide utamanya:
-
Terdapat sebuah grid (Field) yang berisi:
-
Rabbit (kelinci)
-
Fox (rubah)
-
-
Setiap langkah simulasi (step):
-
Rabbit bergerak mencari sel kosong agar tetap hidup.
-
Fox bergerak mencari Rabbit untuk dimakan. Jika tidak ada makanan dan usia/energi habis → mati.
-
-
Struktur umum hewan dimodelkan dalam abstract class
Animal, sedangkan perilaku khusus ditulis diRabbitdanFox.
Konsep OOP yang ditekankan:
-
Abstract Class + Inheritance:
Animal→RabbitdanFox. -
Polymorphism: Simulator hanya bekerja dengan tipe
Animal, tetapi methodact()yang dipanggil bisa milikRabbitatauFoxsesuai objeknya.
4.2 Kode Program Latihan 2
4.2.1 Location.java
public class Location {
private int row;
private int col;
public Location(int row, int col){
this.row = row;
this.col = col;
}
public int getRow(){
return row;
}
public int getCol(){
return col;
}
@Override
public String toString() {
return "(" + row + "," + col + ")";
}
}
4.2.2 Field.java
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
public class Field {
private Object[][] field;
private int depth;
private int width;
public Field(int depth, int width){
this.depth = depth;
this.width = width;
field = new Object[depth][width];
}
public int getDepth() {
return depth;
}
public int getWidth() {
return width;
}
public void clear(Location location){
field[location.getRow()][location.getCol()] = null;
}
public void clear() {
for (int row = 0; row < depth; row++) {
for (int col = 0; col < width; col++) {
field[row][col] = null;
}
}
}
public void place(Object object, Location location){
field[location.getRow()][location.getCol()] = object;
}
public Object getObjectAt(Location location){
return field[location.getRow()][location.getCol()];
}
/**
* Mengembalikan salah satu lokasi kosong di sekitar lokasi yang diberikan
* (dipilih secara acak). Jika tidak ada yang kosong, mengembalikan null.
*/
public Location freeAdjacentLocation(Location location){
List<Location> free = new ArrayList<>();
List<Location> adjacent = adjacentLocations(location);
for(Location loc : adjacent){
if(getObjectAt(loc) == null){
free.add(loc);
}
}
Collections.shuffle(free);
return free.isEmpty() ? null : free.get(0);
}
/**
* Mengembalikan daftar semua lokasi valid di sekitar (8 tetangga).
*/
public List<Location> adjacentLocations(Location location){
List<Location> locations = new ArrayList<>();
int row = location.getRow();
int col = location.getCol();
for(int roffset = -1; roffset <= 1; roffset++){
int nextRow = row + roffset;
if(nextRow >= 0 && nextRow < depth){
for(int coffset = -1; coffset <= 1; coffset++){
int nextCol = col + coffset;
if(nextCol >= 0 && nextCol < width && (roffset != 0 || coffset != 0)){
locations.add(new Location(nextRow, nextCol));
}
}
}
}
return locations;
}
}
4.2.3 Animal.java (Abstract Class)
import java.util.List;
public abstract class Animal {
protected int age;
private boolean alive;
protected Field field;
protected Location location;
public Animal(Field field, Location location){
this.age = 0;
this.alive = true;
this.field = field;
setLocation(location);
}
public boolean isAlive(){
return alive;
}
public void setDead(){
alive = false;
if(location != null){
field.clear(location);
location = null;
field = null;
}
}
public Location getLocation(){
return location;
}
public void setLocation(Location newLocation){
if (location != null){
field.clear(location);
}
location = newLocation;
field.place(this, newLocation);
}
public Field getField(){
return field;
}
/**
* Method abstrak: setiap hewan harus menentukan sendiri
* bagaimana dia berperilaku di setiap langkah simulasi.
*/
public abstract void act(List<Animal> newAnimals);
}
4.2.4 Rabbit.java
import java.util.List;
public class Rabbit extends Animal {
private static final int MAX_AGE = 40;
public Rabbit(Field field, Location location){
super(field, location);
}
@Override
public void act(List<Animal> newAnimals){
age++;
// Jika umur melewati batas, kelinci mati
if (age > MAX_AGE) {
setDead();
}
// Jika masih hidup, coba bergerak ke lokasi kosong di sekitar
if (isAlive()){
Location newLocation = getField().freeAdjacentLocation(getLocation());
if(newLocation != null){
setLocation(newLocation);
} else {
// Tidak ada tempat bergerak → "terjepit" → mati
setDead();
}
}
}
}
4.2.5 Fox.java
import java.util.List;
public class Fox extends Animal {
private static final int MAX_AGE = 150;
private int foodLevel;
public Fox(Field field, Location location){
super(field, location);
foodLevel = 20; // stok makanan awal
}
@Override
public void act(List<Animal> newAnimals){
age++;
foodLevel--;
// Cek batas umur atau kelaparan
if (age > MAX_AGE || foodLevel <= 0) {
setDead();
return;
}
if(isAlive()){
// Coba cari makanan dulu (Rabbit di sekitar)
Location newLocation = findFood();
if(newLocation == null){
// Jika tidak ada makanan, cari lokasi kosong
newLocation = getField().freeAdjacentLocation(getLocation());
}
if(newLocation != null){
setLocation(newLocation);
} else {
// Tidak bisa bergerak kemana-mana → mati karena "terjepit"
setDead();
}
}
}
/**
* Mencari Rabbit pada lokasi-lokasi sekitar.
* Jika ditemukan, Rabbit dimakan (setDead) dan Fox pindah ke lokasi tersebut.
*/
private Location findFood(){
List<Location> adjacent = getField().adjacentLocations(getLocation());
for(Location loc : adjacent){
Object animal = getField().getObjectAt(loc);
if(animal instanceof Rabbit){
Rabbit rabbit = (Rabbit) animal;
if(rabbit.isAlive()){
rabbit.setDead();
// Makan kelinci → menambah foodLevel
foodLevel = 20;
return loc;
}
}
}
return null;
}
}
4.2.6 SimulatorView.java (GUI Sederhana)
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JPanel;
public class SimulatorView extends JPanel {
private static final int GRID_VIEW_SCALING_FACTOR = 6;
private int gridWidth;
private int gridHeight;
private int xScale;
private int yScale;
private Field field;
public SimulatorView(int height, int width) {
gridHeight = height;
gridWidth = width;
setPreferredSize(new Dimension(
width * GRID_VIEW_SCALING_FACTOR,
height * GRID_VIEW_SCALING_FACTOR));
}
public void showStatus(Field field) {
this.field = field;
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (field != null) {
xScale = getWidth() / gridWidth;
if (xScale < 1) {
xScale = GRID_VIEW_SCALING_FACTOR;
}
yScale = getHeight() / gridHeight;
if (yScale < 1) {
yScale = GRID_VIEW_SCALING_FACTOR;
}
for (int row = 0; row < gridHeight; row++) {
for (int col = 0; col < gridWidth; col++) {
Object obj = field.getObjectAt(new Location(row, col));
if (obj != null) {
if (obj instanceof Rabbit) {
g.setColor(Color.ORANGE); // Kelinci
} else if (obj instanceof Fox) {
g.setColor(Color.BLUE); // Rubah
}
g.fillRect(col * xScale, row * yScale, xScale, yScale);
}
}
}
}
}
}
4.2.7 Simulator.java (Main Simulasi)
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.awt.BorderLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.Timer;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Simulator {
private Field field;
private List<Animal> animals;
private int step;
private SimulatorView view;
private JFrame frame;
private JLabel stepLabel;
private JLabel populationLabel;
private static final double FOX_CREATION_PROBABILITY = 0.02;
private static final double RABBIT_CREATION_PROBABILITY = 0.08;
private static final int DEFAULT_DEPTH = 50;
private static final int DEFAULT_WIDTH = 50;
public Simulator() {
this(DEFAULT_DEPTH, DEFAULT_WIDTH);
}
public Simulator(int depth, int width){
step = 0;
animals = new ArrayList<>();
field = new Field(depth, width);
frame = new JFrame("Fox and Rabbit Simulation - Abstract Class");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
stepLabel = new JLabel("Step: 0", JLabel.CENTER);
populationLabel = new JLabel("Population: ", JLabel.CENTER);
view = new SimulatorView(depth, width);
frame.add(stepLabel, BorderLayout.NORTH);
frame.add(view, BorderLayout.CENTER);
frame.add(populationLabel, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
populate();
updateView();
}
public void runLongSimulation() {
Timer timer = new Timer(100, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
simulateOneStep();
}
});
timer.start();
}
public void simulateOneStep(){
step++;
List<Animal> newAnimals = new ArrayList<>();
// Iterasi pada salinan list untuk menghindari ConcurrentModificationException
for (Animal animal : new ArrayList<>(animals)){
if(animal.isAlive()){
animal.act(newAnimals);
} else {
animals.remove(animal);
}
}
animals.addAll(newAnimals);
updateView();
}
private void updateView() {
stepLabel.setText("Step: " + step);
populationLabel.setText(getPopulationDetails());
view.showStatus(field);
}
private String getPopulationDetails() {
int rabbitCount = 0;
int foxCount = 0;
for (Animal animal : animals) {
if (animal instanceof Rabbit) {
rabbitCount++;
} else if (animal instanceof Fox) {
foxCount++;
}
}
return "Population - Rabbit: " + rabbitCount + " | Fox: " + foxCount;
}
private void populate(){
Random rand = new Random();
field.clear();
animals.clear();
int depth = field.getDepth();
int width = field.getWidth();
for(int row = 0; row < depth; row++){
for(int col = 0; col < width; col++){
Location location = new Location(row, col);
double prob = rand.nextDouble();
if(prob <= FOX_CREATION_PROBABILITY){
Fox fox = new Fox(field, location);
animals.add(fox);
}
else if(prob <= FOX_CREATION_PROBABILITY + RABBIT_CREATION_PROBABILITY){
Rabbit rabbit = new Rabbit(field, location);
animals.add(rabbit);
}
}
}
}
public static void main(String[] args) {
Simulator simulator = new Simulator();
simulator.runLongSimulation();
}
}
4.3 Penjelasan Konsep OOP pada Latihan 2
-
Abstract Class dan Polymorphism
-
Animaladalah abstract class yang mendefinisikan kerangka umum hewan (age,alive,field,location, dan methodact). -
RabbitdanFoxmeng-override methodact()dengan logika masing-masing. -
Di
Simulator, listanimalsbertipeList<Animal>, tapi isi sebenarnya bisa berupaRabbitatauFox. Saatanimal.act(newAnimals)dipanggil, Java menjalankan versi method yang sesuai tipe konkret objek tersebut.
-
-
Encapsulation
-
Atribut
age,alive,field,locationdikelola melalui method sepertisetDead(),setLocation(), danisAlive().
-
-
Perilaku Spesifik
-
Rabbit:
-
Fokus bertahan hidup melalui gerakan.
-
Mati jika umur melewati
MAX_AGEatau tidak punya tempat bergerak.
-
-
Fox:
-
Memiliki
foodLevelsebagai representasi energi. -
Mencari
Rabbitdi sekitar sebagai makanan (methodfindFood()). -
Jika tidak makan dalam beberapa langkah,
foodLevelhabis → mati.
-
-
-
Catatan Kritis
-
Simulasi di atas masih sederhana:
-
Belum ada mekanisme reproduksi (
newAnimalsbelum digunakan untuk menambah hewan baru). -
Pola populasi cenderung menuju kepunahan (tanpa kelahiran, hanya ada kematian).
-
-
Namun, dari sisi konsep abstract class & polymorphism, struktur ini sudah menunjukkan:
-
Satu abstract class
Animaldapat menjadi dasar banyak jenis hewan. -
Simulator cukup mengetahui
Animal, tidak perlu tahu detail tiap subclass.
-
-
Tidak ada komentar:
Posting Komentar