20 Januari, 2010

Kelas Generik


Selain pada fungsi, konsep template dapat diterapkan juga pada kelas. Misalnya dengan menggunakan contoh Stack yang sudah diberikan dan dengan fasilitas template ini, perancang kelas dapat dengan mudah menciptakan Stack of integer, Stack of double, Stack of character, Stack of Complex, Stack of Process, Stack of String, dsb.
Fasilitas template C++ memberikan kemungkinan untuk membangkitkan kelas-kelas di atas melalui instansiasi dari kelas generik. Untuk menciptakan kelas generik, perancang kelas harus dapat mengidenti_kasi parameter-parameter mana yang menentukan sifat kelas. Dalam contoh Stack yang diberikan parameter yang menentukan kelas adalah jenis int yang berkaitan dengan data yang disimpan di dalam Stack. Deklarasi kelas Stack yang ditunjukkan pada Contoh 3.2 dapat diubah menjadi deklarasi kelas Stack generik seperti pada Contoh di bawah ini

Contoh Deklarasi kelas Stack generik
 template <class Type>
 class Stack {
 public:
 // ctor-cctor-dtor
 Stack(); // default ctor
 Stack (int); // ctor dengan ukuran max stack
 Stack (const Stack&); // cctor
 ~Stack();

 // services
 void Push (Type); // <=== parameter generik
 void Pop (Type&); // <=== parameter generik
 int isEmpty() const;
 int isFull() const;
 // operator
 Stack& operator= (const Stack&);
 void operator<< (Type); // <=== parameter generik
 void operator>> (Type&); // <=== parameter generik

 private:
 const int defaultStackSize = 500; // ANSI: tidak boleh inisialisasi
 int topStack;
 int size;
 Type *data; // <=== parameter generik
 };

Untuk menciptakan objek dari kelas generik, pemrogram menuliskan deklarasi objek dengan sintaks:
kls-generik < tipe-instansiasi > objek ;

Stack<int> a; // Stack of integer
Stack<double> b (30); // Stack of double, kapasitas maks = 30
Stack<Complex> c; // Stack of Complex




CATATAN:
·         nama Stack<int>, Stack<double>, ... dapat dipandang sebagai nama tipe baru!
·         Definisi fungsi anggota harus dituliskan sebagai fungsi template dan scope yang semula dituliskan sebagai Stack:: harus dituliskan sebagai Stack<Type>::. Hal ini harus dilakukan untuk seluruh fungsi anggota kelas tersebut. Sebagai contoh, konstruktor dan fungsi anggota Push() dituliskan sebagai fungsi template berikut ini:

template <class Type>
Stack<Type>::Stack ()
{
size = defaultStackSize;
topStack = 0;
data = new TYPE [size];
}
template <class Type>
void Stack<Type>::Push (Type item)
{
// ...
if (!isFull()) {
data [topStack] = item;
topStack++;
}
// ...
}

Sebelumnya dijelaskan bahwa dalam penulisan kelas ke dalam file, bagian deklarasi kelas dituliskan ke file X.h dan bagian definisi fungsi-fungsi anggota dituliskan ke file X.cc. Jika kelas generik digunakan untuk mendeklarasikan kelas, maka baik deklarasi kelas generik maupun de_nisi fungsi generik dituliskan ke dalam file X.h. Sehingga untuk contoh Stack di atas, keduanya dituliskan di dalam file Stack.h.
·         Di luar konteks de_nisi kelas generik, nama tipe yang dapat digunakan (misalnya oleh fungsi, deklarasi variabel/objek, dsb.) adalah nama tipe hasil instansiasi. Dalam contoh di atas tipe hasil instansiasi adalah Stack<int>, Stack<double>, and Stack<Complex>.
Hal ini juga berlaku pada fungsi anggota kelas. Jika misalkan ada fungsi anggota kelas generik Stack::Reverse() yang memerlukan objek lokal bertipe Stack yang generic maka deklarasinya adalah:
template <class Type>
void Stack<Type>::Reverse() {
Stack<Type> stemp; // objek lokal yang generik
// ...algoritma dari Reverse()...
}

Untuk efisiensi pemanfaatan kelas generik, sebaiknya digunakan member initialization list
di dalam constructor maupun copy constructor.




Pointer implisit this


Setiap objek dari suatu kelas memiliki sendiri salinan anggota data dari kelas tersebut. Namun, hanya ada satu salinan anggota fungsi untuk objek-objek dari kelas tersebut. Dengan kata lain, jika ada dua objek dari suatu kelas yang memanggil salah satu fungsi anggota kelas tersebut maka kedua objek akan menjalankan rangkaian instruksi yang terletak pada lokasi memori yang sama, tetapi anggota data yang diakses oleh fungsi anggota tersebut terletak pada dua lokasi memori yang berbeda.
Untuk menangani hal di atas, setiap function member secara implisit memperoleh argument (parameter aktual) tersembunyi berupa pointer ke objek (implicit this pointer). Jika pointer this ini akan digunakan di dalam fungsi anggota Push di atas, setiap pengaksesan terhadap data anggota (maupun fungsi anggota) kelas Stack dapat diawali dengan `this->'.

void Stack::Push (int item) {
// . . .
this->data [this->topStack] = item;
this->topStack++;
// . . .
}

Dalam contoh berikut di atas, perhatikanlah bahwa parameter formal item tidak dapat dituliskan sebagai this->item karena bukan merupakan anggota kelas Stack.
Pointer this merupakan sebuah rvalue sehingga ekspresi assignment terhadap this dalam
contoh berikut tidak diijinkan:

this = ...; // ruas kanan diisi suatu ekpresi

Mengapa ada this pointer?
·         Pointer implisit this untuk kelas X, dideklarasikan sebagai X* this, dan digunakan untuk mengakses member di dalam kelas tersebut
·         Pointer this dapat juga digunakan memberikan return value yang berjenis kelas tersebut (misalnya fungsi operator).



Class

 Konsep kelas dalam C++ ditujukan untuk menciptakan tipe data baru. Sebuah tipe terdiri dari kumpulan bit yang merepresentasikan nilai abstrak dari instansiasi tipe tersebut serta kumpulan operasi terhadap tipe tersebut. Sebagai contoh int adalah sebuah tipe karena memiliki representasi bit dan kumpulan operasi seperti \penambahan dua variabel bertipe int", \perkalian dua variabel bertipe int", dsb.
Dengan cara yang sama, sebuah kelas juga menyediakan sekumpulan operasi (biasanya public) dan sekumpulan data bit (biasanya non-public) yang menyatakan nilai abstrak objek dari kelas tersebut.
Hubungan antara kelas dengan objek dapat dinyatakan dengan analogi berikut:
class vs. object = type vs. variable

Pendeklarasian kelas (terutama fungsi anggotanya) menentukan perilaku objek dalam operasi penciptaan, pemanipulasian, pemusnahan objek dari kelas tersebut. Dalam pemrograman dengan bahasa yang berorientasi objek dapat dilihat adanya peran perancang kelas dan pengguna kelas. Perancang kelas menentukan representasi internal objek yang berasal kelas yang dirancangnya.
Pendeklarasian kelas dilakukan seperti pende_nisian sebuah struktur namun dengan mengganti kata kunci struct dengan class. Kata kunci class dalam C++ dapat dipandang sebagai perluasan dari kata kunci struct, hanya perbedaannya nama kelas (tag-name) dalam C++ sekaligus merupakan tipe baru.

Contoh Sebuah struct yang memiliki prosedur/fungsi
struct Stack { // nama tag "Stack" sekaligus menjadi tipe baru
 /*******************
 * function member *
 *******************/
 void Pop(int&);
 void Push (int);
 int isEmpty();
 // ... definisi fungsi lainnya

 /***************
 * data member *
 ***************/
 int topStack;
 int *data;
 // ... definisi data lainnya
 };

Sebuah kelas memiliki satu atau lebih member (analog dengan _eld pada struct). Ada dua jenis member:
·         Data member, yang merupakan representasi internal dari kelas
·         Function member, kumpulan operasi (service/method) yang dapat diterapkan terhadap objek, seringkali disebut juga sebagai class interface

Setiap _eld yang dimiliki sebuah struct dapat secara bebas diakses dari luar struktur tersebut. Hal ini berbeda dibandingkan dengan pengaksesan terhadap anggota kelas. Hak akses dunia luar terhadap anggota (data dan fungsi) diatur melalui tiga kata kunci private, public, dan protected. Setiap fungsi anggota kelas selalu dapat mengakses data dan fungsi anggota kelas tersebut (dimanapun data tersebut dideklarasikan: private, public, protected). Sedangkan fungsi bukan anggota kelas hanya dapat mengakses anggota yang berada di bagian public. Hak akses terhadap fungsi dan data anggota kelas dinyatakan dalam Tabel dibawah ini.

Wilayah member di deklarasikan
Makna
public
dapat diakses oleh fungsi di luar kelas (fungsi bukan anggota kelas tersebut) dengan menggunakan operator selektor (. atau ->)
private
hanya dapat diakses oleh fungsi anggota kelas tersebut
protected
hanya dapat diakses oleh fungsi anggota kelas tersebut dan fungsi-fungi anggota kelas turunan


Dalam deklarasi \kelas" Stack pada Contoh diatas, semua anggota bersifat public, karena hal ini sesuai dengan sifat sebuah struct. Namun jika, kata kunci \struct" diganti menjadi \class", maka semua anggota otomatis bersifat private.
Dalam contoh tersebut, fungsi-fungsi anggota Pop(), Push(), dsb hanya dideklarasikan namun belum dide_nisikan. Pende_nisian anggota fungsi dapat dilakukan dengan dua cara:
·         Di dalam class body, otomatis menjadi inline function
·         Di luar class body, nama fungsi harus didahului oleh class scope

Contoh dibawah menyajikan deklarasi kelas Stack dengan menggunakan kata kunci class 3
Contoh Deklarasi kelas Stack beserta fungsi anggota
class Stack {
public:
// function member
void Pop(int& ); // deklarasi (prototype)
void Push (int); // deklarasi (prototype)
/*--- pendefinisian di dalam class body ---*/
int isEmpty() {
return topStack == 0;
}
private:
// data member
int topStack; /* posisi yang akan diisi berikutnya */
int *data;
}; // PERHATIKAN TITIK KOMA !!!
// pendefinisian member function Pop di luar
// class body
void Stack::Pop(int& item) {
if (isEmpty()) {
// error message
}
else {
topStack--;
item = data [topStack];
}
} // TIDAK PERLU TITIK KOMA !!!
void Stack::Push (int item) {
if (isFull()) {
// error message
}
else {
data [topStack] = item;
topStack++;
}
}

16 Januari, 2010

Interface vs. Class

  Persamaan:
       Interface dan class adalah sama-sama sebuah type
       Hal ini berarti bahwa interface dapat digunakan di tempat dimana sebuah class dapat digunakan
       Interface dan class, keduanya dapat mendefinisikan method
       Sebagai contoh:
PersonInterface               pi = new Person();
Person                                  pc = new Person();

  Perbedaan:
       Anda tidak dapat membuat instance dari sebuah interface
       Interface tidak memiliki segala implementasi dari method
       Sebagai contoh:
PersonInterface               pi = new PersonInterface(); //ERROR!




Interface vs. Abstract Class

       Semua interface method tidak memiliki body
       Beberapa Abstract class memiliki method dengan implementasi
       Sebuah interface hanya dapat didefinisikan constant
       Sebuah abstract class tampak seperti class biasa yang dapat mendeklarasikan variabel.
       Interface tidak memiliki hubungan inheritance secara langsung dengan setiap class tertentu, mereka didefinisikan secara independen.
       Abstract class dapat di-subclass-kan




Meng-extends Class vs. Implementasi interface

       Sebuah class hanya bisa meng-EXTENDS SATU superclass, tetapi juga bisa meng-IMPLEMENTASIKAN BANYAK interface
       Sebagai contoh:       
public class Person implements PersonInterface,
                        LivingThing,
                        WhateverInterface {
   //beberapa kode disini
}

       Contoh lain:
public class ComputerScienceStudent extends Student
                        implements PersonInterface,
                                  LivingThing {
   //Beberapa kode disini
}




Abstract class

o   Sebuah class yang tidak bisa diinstansiasi
o   Sering muncul pada puncak hierarki class object-oriented programming(OOP), mendefinisikan segala type action/tindakan yang mungkin dengan object semua subclass dari class

o   Method abstract
       Method di dalam abstract class tidak mempunyai implementasi
       Untuk membuat abstract method, tulis saja deklarasi method tanpa body dan gunakan keyword abstract
o   Sebagai contoh,
public abstract void someMethod();

Contoh Abstract Class
public abstract class LivingThing {
   public void breath(){
     System.out.println("Living Thing breathing...");
   }
   public void eat(){
     System.out.println("Living Thing eating...");
   }
   /** 
    * abstract method walk 
    * Kita ingin method ini di-overrride oleh subclass dari 
    * LivingThing 
    */
   public abstract void walk();
}

o   Ketika sebuah class meng-extends abstract class LivingThing, diwajibkan meng-override abstract method walk(), jika tidak, subclass tersebut juga akan menjadi abstract class, dan oleh karena itu tidak bisa diinstansiasi
o   Sebagai contoh,
public class Human extends LivingThing {
   public void walk(){
        System.out.println("Human walks...");
   }
}

o   Menggunakan abstract class untuk mendefinisi jenis-jenis yang luas dari behavior yang ada di puncak hirarki class object-oriented programming, dan menggunakan subclassnya untuk menyediakan detail implementasi dari abstract class.


Casting Object

Instance dari class juga dapat di-casting menjadi instance dari class lain, dengan satu batasan ::
       Class asal dan tujuan harus direlasikan dalam inheritance, salah satu class harus berupa subclass dari class lain.
       Casting object digunakan untuk mengkonversi nilai primitif menuju tipe yang lebih besar, beberapa object tidak perlu mengalami casting secara explisit.

Gunakan sintaks berikut untuk casting object,
   (classname)object

classname           - nama class tujuan
object                   - reference untuk object asal

Berikut ini merupakan contoh proses casting sebuah instance dari class VicePresident ke instance dari class Employee.
VicePresident merupakan subclass dari class Employee dengan beberapa informasi tambahan.

Employee emp = new Employee();
VicePresident veep = new VicePresident();

emp = veep;

// casting explisit
veep = (VicePresident)emp; 


Class dan method final

Final Class
       Class yang tidak bisa di-extends
       Untuk mendeklarasikan final class, kita tulis,
public final ClassName{
   . . .
}

Contoh:
public final class Person {
   . . .
}

Contoh lain dari final class adalah class wrapper dan String.

Method Final
       Method yang tidak bisa di-override
       Untuk mendeklarasikan final method, kita tulis,
        public final [returnType]    [methodName]([parameters]){
   . . .
}


method static secara otomatis merupakan method final.

Contoh
public final String getName(){
   return name;
}


Meng-override method

       Jika sebuah subclass menginginkan implementasi yang berbeda terhadap method dari superclassnya, maka salah satu caranya dapat dilakukan dengan meng-override method bersangkutan.
       Sebuah subclass dapat meng-override method superclassnya dengan menyediakan sebuah implementasi baru untuk method tersebut.

berikut ini merupakan implementasi dari method getName didalam superclass Person
public class Person {
     :
     :
     public String getName(){
           System.out.println("Parent: getName");
           return name;
     }
}

       Untuk meng-override method getName dari superclass Person, di dalam subclass Student, kita tulis :
public class Student extends Person{
   :
   :
   public String getName(){
        System.out.println("Student: getName");
        return name;
   }
   :
}

       Sekarang, ketika kita memanggil method getName dari object subclass Student, method getName yang di-override akan dipanggil, dan hasilnya akan menjadi,
student: getName 



Keyword “super”

       Sebuah subclass dapat juga memanggil secara eksplisit sebuah constructor superclass yang ada diatasnya.
       Dapat dilakukan dengan menggunakan pemanggilan constructor super.
       Pemanggilan constructor super didalam constructor subclass akan mengakibatkan eksekusi dalam constructor yang relevan dari superclass, berdasarkan passing argument-nya.

       Sebagai contoh, pada contoh sebelumnya yaitu class Person dan Student, kita tunjukkan sebuah contoh pemanggilan constructor super.
       Tuliskan kode berikut untuk class Student
public Student(){
   super( "SomeName", "SomeAddress" );
   System.out.println("Inside      Student:Constructor");
}

Beberapa hal untuk diingat ketika menggunakan pemanggilan constructor super :
       Pemanggilan super() HARUS DIJALANKAN SESUAI DENGAN STATEMENT PERTAMA DALAM SEBUAH CONSTRUCTOR.
       Pemanggilan super() hanya dapat digunakan di dalam definisi constructor.
       Hal ini menjelaskan bahwa constructor this() dan pemanggilan super() TIDAK DAPAT DIJALANKAN SECARA BERSAMAAN DI DALAM CONSTRUCTOR YANG SAMA.

Penggunaan lainnya dari super mengarah pada member dari superclass.
Sebagai contoh,
public Student() {
     super.name = “somename”;
     super.address = “some address”;
}


12 Januari, 2010

Interface

       Adalah semacam blok spesial yang hanya berisi tanda tangan method (dan mungkin konstan).
       Menggambarkan tandatangan dari seperangkat method, tanpa body
       Menggambarkan cara standard dan publik penetapan behavior class
       Mengijinkan class,dengan mengabaikan lokasi mereka di dalam hirarki class untuk menerapkan behavior.
       CATATAN: Interface memperlihatkan polymorphism juga, sejak program diperbolehkan memanggil sebuah method interface, dan versi yang sesuai dari method tersebut akan dieksekusi tergantung pada jenis object yang dilewatkan kepada pemanggilan method interface

Mengapa menggunakan interface?
       Untuk memiliki class yang tidak berhubungan yang mengimplementasikan method yang sama.
       Contoh:
   Class Line dan MyInteger
       Tidak berhubungan
       Keduanya mengimplementasikan method perbandingan
   isGreater
   isLess
   isEqual
       Untuk mengungkapkan sebuah interface pemrograman object tanpa pernyataan classnya
       Untuk model multi inheritance yang mengijinkan sebuah class untuk memiliki lebih dari satu superclass.

Membuat interface
       Untuk membuat sebuah interface, kita tulis:
public interface [InterfaceName] {
     //beberapa method tanpa body
}

       Sebagai contoh, mari buat sebuah interface yang mendefinisikan hubungan antara dua object sesuai dengan pesanan dari object.
public interface Relation
{
public boolean isGreater( Object a, Object b);
public boolean isLess( Object a, Object b);
public boolean isEqual( Object a, Object b);
}

       Untuk menggunakan interface, kita gunakan keyword implements
       Sebagai contoh,
/**
 * Class ini menjelaskan segment garis
 */
public class Line implements Relation {
   private double x1;
   private double x2;
   private double y1;
   private double y2;
public Line(double x1, double x2, double y1, double y2){
        this.x1 = x1;  
        this.x2 = x2;  
        this.y1 = y1;       
        this.y2 = y2;  
   }

public double getLength(){
           double length = Math.sqrt((x2-x1)*(x2-x1) +
                                (y2-y1)* (y2-y1));  
           return length;
     }
    
     public boolean isGreater( Object a, Object b){
           double aLen = ((Line)a).getLength();
           double bLen = ((Line)b).getLength();
           return (aLen > bLen);
     }
    
     public boolean isLess( Object a, Object b){
           double aLen = ((Line)a).getLength();
           double bLen = ((Line)b).getLength();
           return (aLen < bLen);
          
     }
    
     public boolean isEqual( Object a, Object b){
           double aLen = ((Line)a).getLength();
           double bLen = ((Line)b).getLength();
           return (aLen == bLen);
     }         
}

       Ketika class Anda mencoba untuk mengimplementasikan sebuah interface, pastikan selalu bahwa Anda mengimplementasikan semua method dari interface tersebut, jika tidak, Anda akan mendapatkan kesalahan ini.
Line.java:4: Line is not abstract and does not override abstract method isGreater(java.lang.Object,java.lang.Object) in Relation
public class Line implements Relation
       ^
1 error