Dart. 13 - Operator Overloading, Generic & Exception

 






Operator Overloading

Operator Overloading adalah cara mengubah tujuan/fungsi dari operator bawaan Dart untuk melakukan operasi/fungsi yang kita inginkan yang kita defenisikan pada kelas, misalnya operator + digunakan untuk menjumlahkan dua buah bilangan, akan tetapi operator ini akan di Overload pada saat kita menggunakan operator + ini pada String, yaitu “a” + “b” = “ab”, operator tersebut tidak akan menjumlahkan a+b akan tetapi akan melakukan penggabungan, dari contoh ini kita bisa mengerti arti dari Overloading Operator.

Kelas Point Dari Paket dart:math

Contoh lain dari operator overloading adalah librari kelas Point dari paket dart:math. Library tersebut meng-overload operator +, -, * dan ==. Kelas Point mewakili lokasi dua dimensi dengan titik koordinat x, y. Bagaimana caranya dua Point dijumlahkan? Misalnya: Point a mewakili lokasi x1, y1 dan Point b mewakili lokasi x2, y2, maka penjumlahan kedua Point (a+b) adalah x1+x2, y1+y2, penggunaan operator tetap sama. 

Berbeda dengan operator * (perkalian), operator ini tidak bisa digunakan dengan objek Point lainnya tetapi dengan angka secara langsung, artinya kita tidak akan bisa melakukan operasi perkalian atara dua buah objek Point, misalnya: a * b akan mengakibatkan error, namun kita bisa melakukan operasi berikut a = a * 2 menjadi (x1*2, y1*2). Perhatikan contoh kode berikut:

import "dart:math"; void main() { Point a = new Point(2, 2); Point b = new Point(4, 4); // ingat bahwa a dan b merupakan objek dari kelas Point // dimana b mewakili (4,4) dan a mewakili (2,2) // sehingga b = b - a adalah b = (4-2, 4-2) menjadi (2,2) b = b - a; print(b); // print Point(2, 2) //a = a * b; menyebakan error // a = a * 2 adalah (2*2, 2*2) menjad (4,4) a = a * 2; print(a); // print Point(4,4) // a = b + a adalah a = (2+4, 2+4) menjad (6,6) // b menjadi (2,2) karena proses sebelumnya b = b - a; a = b + a; print(a); // print Point(6,6) if ((b + b) == (a - b)) { // ini kondisi benar print("Kedua sisi memiliki nilai yang sama"); } }

Overloading Operator Pada Kelas Kita Sendiri.

Overloading suatu operator kelas yang kita buat harus menggunakan keyword operator. Sebagai contoh, kita memiliki kelas Population yang mendefenisikan populasi sebuah kota, kelas tersebut mempunyai dua buah variabe, name untuk nama kota dan pop untuk populasi, kelas tersebut akan meng-overload operator & dan +, ketika kita ingin menyajikan kombinasi populasi dari dua buah kota kita bisa menggunakan operator &, dan operator + untuk menambahkan orang kedalam populasi dari kota tersebut. 

class Population {
  String name;
  int pop;

  Population(this.name, this.pop);

  operator &(Population other) =>
      new Population(name + " & " + other.name, pop + other.pop);

  operator +(int newPeople) => pop += newPeople;

  String toString() {
    return "$name has a population of $pop";
  }
}

void main() {
  Population medan = new Population("Medan", 2500);
  Population jakarta = new Population("Jakarta", 5000);

  Population medan_jakarta = medan & jakarta;
  print(medan_jakarta);

  jakarta + 1000;
  print(jakarta); // print: Jakarta has a population of 6000
}

Contoh Lain

class Kubus {
  int sisi;

  Kubus(this.sisi);

  operator +(int newSisi) => sisi += newSisi;
  operator -(int newSisi) {
    if (sisi < newSisi) {
      print("Sisi tidak boleh minus");
    } else {
      sisi -= newSisi;
    }
  }

  String toString() {
    return "$sisi";
  }
}

void main() {
  Kubus k1 = new Kubus(10);
  print(k1);

  k1 + 10; // print 20
  print(k1);

  k1 - 15; // print 5
  print(k1);

  k1 - 50; // print("sisi tidak boleh minus")
  print(k1); //print 5 nilai terakhir dari sisi
}

Kembali ke kelas Point sebelumnya, seperti yang kita tahu bahwa Dart bersifat open-source, artinya source kode untuk semua librarynya termasuk paket dart:math dapat kita lihat langsung, berikut adalah potongan dari kode kelas Point dari librari dart:math 

bool operator ==(other) {
 if (other is !Point) return false;
 return x == other.x && y == other.y;
}

Point<T> operator +(Point<T> other) {
 return new Point<T>(x + other.x, y + other.y);
}

Point<T> operator -(Point<T> other) {
 return new Point<T>(x - other.x, y - other.y);
}

Point<T> operator *(num factor) {
 return new Point<T>(x * factor, y * factor);
}

Bisa kita lihat, untuk operator + dan - digunakan untuk objek dari kelas Point, sedangkan operator * hanya bisa digunakan langsung dengan angka, adapun sintaks Point<T> adalah Generic yang akan kita bahas selanjutnya. 

Generics

Pada materi List dan Map sebelumnya kita pernah membuat kode dengan fitur generics, kita mempunyai pilihan untuk mendeklarasikan List atau Map dengan menentukan objek apa yang akan diberikan pada List atau Map. Perhatikan contoh kode berikut: 
List fruits1 = ["apel", "pisang", "jeruk"]; List<String> fruits2 = ["apel", "pisang", "jeruk"];

Dari potongan kode tersebut, kita bisa meliha perbedaan antara fruits1 dan fruits2, yaitu fruits2 hanya bisa diisi oleh String, hal yang cukup menarik adalah deklarasi type pada Dart adalah optional, akan tetapi tujuan dari menggunakan tipe data bukan untuk membatasi kode kita tetapi agar kode kita lebih mudah terbaca, menggunakan tipe data juga dapat menolong kita mencegah error. 

Generics adalah cara agar kode kita bekerja dengan tipe tertentu, kita dapat menggunakan fitur generics pada kelas yang kita buat, kita membuat generic dengan sintaks <TypeName>, perhatikan contoh berikut: 
//deklarasi kelas dengan fitur generics class CetakPesan<T> { int jumlahCetak; T pesan; CetakPesan(this.jumlahCetak, this.pesan); void cetak() { for (int i = 0; i < jumlahCetak; i++) { print(pesan); } } } void main() { // cetakPesan dengan tipe integer CetakPesan<int> cetakPesan = CetakPesan(5, 100); cetakPesan.cetak(); // cetakPesan2 dengan tipe String CetakPesan<String> cetakPesan2 = CetakPesan(5, "Hello, World"); cetakPesan2.cetak(); }

Dari contoh program dapat kita lihat, bahwa kelas CetakPesan dapat bisa bekerja dengan tipe apapun. 

Exception

Secara sederhana Exception dapat diartikan sebagai “kejadian yang tak terduga pada saat program berjalan” atau secara umum, user akan menyebutnya error. Jika error tidak ditangani maka program akan mengalami crash/hang atau mungkin saja akan berhenti.

Bekerja dengan Exception built-in pada Dart

Dart memiliki banyak kelas-kelas exception yang siap digunakan, Exception dapat ditangani dengan menggunakan blok try-catch, kode yang diperkirakan akan menghasilkan exception akan kita jalankan pada blok try-catch, sehingga program tidak akan mengalami crash/hang, Dart juga memiliki keyword on, yang bekerja mirip dengan blok catch. Perhatikan kode berikut, kode pertama adalah kode tanpa exception dan yang kedua dengan exception.

import 'dart:io';

void main() {
  String intTemp = stdin.readLineSync();
  int answer = int.parse(intTemp);
  print(answer);
}


import 'dart:io';

void main() {
  print("Input Sebuah Nilai: ");
  String intTemp = stdin.readLineSync();
  int userAnswer;

  try {
    userAnswer = int.parse(intTemp);
    print(userAnswer);
  } on FormatException {
    print("Terjadi Kesalahan");
  }

  print("ini masih dijalankan");
  print("program tidak crash karena exception ditangani");
}
Dari contoh kode pertama pada saat metode parse() dieksekusi, maka metode tersebut akan melemparkan exception kelas FormatException jika intTemp berisi String huruf (“ab”, “hello”) dan program akan crash/hang karena exception tidak ditangani.

Dari contoh kode kedua sama halnya dengan kode pertama, akan tetapi jika terjadi exception maka program tidak akan crash/hang, karena exception ditangani menggunakan blok try-catch/try-on, sehingga jika terjadi exception makan pesan “Terjadi Kesalahan” akan di kerjakan, dan program akan terus berjalan sampai selesai.

Perbedaan antara try-on dan try-catch adalah dengan try-catch kita bisa mengetahui jenis kesalahannya karena dengan try-catch kita bisa mencetak pesan dari Exception tersebut, perhatikan contoh berikut:

import 'dart:io';

void main() {
  print("Input Sebuah Nilai: ");
  String intTemp = stdin.readLineSync();
  int userAnswer;

  try {
    userAnswer = int.parse(intTemp);
    print(userAnswer);

  } catch (exception) {
    print("Terjadi Kesalahan");
    //kita bisa mencetak pesan dari exception yang terjadi
    print(exception);
  }

  print("ini masih dijalankan");
  print("program tidak crash karena exception ditangani");
}
Blok try-catch juga bisa menampung stack trace, yang menjelaskan bagaimana kita menangka exception yang terjadi, variabel yang menangani stacktrace berada pada argumen kedua dari parameter blok catch, perhatikan contoh berikut:

import 'dart:io';

void main() {
  print("Input Sebuah Nilai: ");
  String intTemp = stdin.readLineSync();
  int userAnswer;

  try {
    userAnswer = int.parse(intTemp);
    print(userAnswer);

  } catch (exception, stacktrace) {
    print("Terjadi Kesalahan");
    //kita bisa mencetak pesan dari exception yang terjadi
    print(exception);
    print(stacktrace);
  }

  print("ini masih dijalankan");
  print("program tidak crash karena exception ditangani");
}
Terdapat juga blok try-catch-finally, dimana blok finally akan tetap dijalankan walaupun blok try menangkap atau tidak menangkap kesalahan.

import 'dart:io';

void main() {
  print("Input Sebuah Nilai: ");
  String intTemp = stdin.readLineSync();
  int userAnswer;

  try {
    userAnswer = int.parse(intTemp);
    print(userAnswer);

  } catch (exception, stacktrace) {
    print("Terjadi Kesalahan");
//kita bisa mencetak pesan dari exception yang terjadi
print(exception);
print(stacktrace);
  } finally {
print(“block finally akan tetap dijalankan”);
print(“walaupun exception terjadi atau tidak”);
  }

  print("ini masih dijalankan");
  print("program tidak crash karena exception ditangani");
}

Membuat Kelas Exception Sendiri

Sama seperti yang lain pada dart, exception hanyalah objek, kita bisa membuat kelas exception kita sendiri dengan menciptakan kelas yang mengimplementasikan interface Exception, hal yang menarik adalah interface Exception tidak memiliki metode apapun untuk diimplementasikan, untuk menggunakan kelas Exception yang kita buat, kita harus menggunakan keyword throw. Perhatikan contoh program berikut:

class BagiNolException implements Exception {
  String pesan;

  BagiNolException(this.pesan);

  String toString() {
    return pesan;
  }
}

class Aritmatika {
  double bagi(x, y) =>
      y != 0 ? x / y : throw BagiNolException("Pembagian Dengan Nol");
}

void main() {
  Aritmatika aritmatika = Aritmatika();

  // ingat bahwa exception harus ditanggkap dengan block try-on / try-catch
  try {
    print(aritmatika.bagi(2, 5));
    print(aritmatika.bagi(2, 0));
  } catch (e) {
    print(e);
  }
  print("baris ini masih dieksekusi");

  // jadikan kode blok try sampai print menjadi komentar
  // hapus tanda komentar pada kode print dibawah, dan bandingkan hasilnya.

  //print(aritmatika.bagi(2, 5));
  //print(aritmatika.bagi(2, 0));
  //print("baris ini masih dieksekusi");
}
Dart. 13 - Operator Overloading, Generic & Exception Dart. 13 - Operator Overloading, Generic & Exception Reviewed by jc on January 18, 2021 Rating: 5

No comments:

Powered by Blogger.