Bài giảng Giới thiệu về lớp và đối tượng trong Java
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Giới thiệu về lớp và đối tượng trong Java", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
Tài liệu đính kèm:
- bai_giang_gioi_thieu_ve_lop_va_doi_tuong_trong_java.ppt
Nội dung text: Bài giảng Giới thiệu về lớp và đối tượng trong Java
- LECTURE 2 GIỚI THIỆU VỀ LỚP VÀ ĐỐI TƯỢNG TRONG JAVA 1. Các khái niệm cơ bản: class, kế thừa (inheritance), trừu tượng (abstract), đa hình (polymorphism), interface, constructor., từ khóa final. Ý nghĩa của chúng trong việc trừu tượng hóa các đối tượng. 2. Khái niệm overload, override 3. Ép kiểu (casting) , từ khóa instance of, auto-boxing (Java 5 trở lên) 4. Khái niệm về phạm vi class (public, private, nested class), 5. phạm vi method (public, private, protected).
- PHẦN 1 LỚP (CLASS)
- KHÁI NIỆM LỚP (CLASS) • Lớp được xem như một khuôn mẫu (template) của đối tượng (Object). • Trong lớp bao gồm các thuộc tính của đối tượng (properties) và các phương thức (methods) tác động lên các thuộc tính. • Đối tượng được xây dựng từ lớp nên được gọi là thể hiện của lớp (class instance). 3
- KHAI BÁO LỚP class { ; ; constructor1 constructor2 method_1 method_2 class } • class: là từ khóa của java • ClassName: là tên chúng ta đặt cho lớp • field_1, field_2: các thuộc tính (các biến, hay các thành phần dữ liệu của lớp) • Constructor1, constructor2: là phương thức xây dựng, khởi tạo đối tượng của lớp. • method_1, method_2: là các phương thức (có thể gọi là hàm) thể hiện các thao tác xử lý, tác động lên các thuộc tính của lớp. • Sử dụng lớp: ClassName objName; 4 objName = new ClassName(tham số);
- THUỘC TÍNH CỦA LỚP • Vùng dữ liệu (fields) hay thuộc tính (properties) của lớp được khai báo bên trong lớp như sau: class { // khai báo những thuộc tính của lớp field1; // } • Để xác định quyền truy xuất của các đối tượng khác đối với vùng dữ liệu của một lớp người ta thường dùng 5 tiền tố sau: – public, – private – protected – Và tiền tố đặc biệt rỗng – static: dữ liệu static chứa giá trị trong vùng nhớ chung, không thể dùng cho 5 lớp ngoài cùng.
- private và protected • private: Sử dụng private để ẩn hoàn toàn các thành phần của lớp (dữ liệu, phương thức), chúng sẽ không thể được truy nhập từ bên ngoài lớp. • protected: Sử dụng protected để cho phép các thành phần của class được truy nhập bởi các subclass trong bất kỳ package nào, hoặc các class trong cùng package. • 2 từ khóa trên chỉ có thể sử dụng cho các thành phần của class, không thể sử dụng cho class ngoài cùng. 6
- public và default modifiers • no modifier: Sử dụng default modifier (no modifier) thì các thành phần của class được truy nhập từ bất kỳ lớp nào trong cùng package, nhưng không thể từ package khác. • public: Sử dụng public cho phép các thành phần của class có thể được truy nhập từ bất kỳ lớp nào. • public và default modifier có thể được sử dụng cho các thành phần của class, cũng như sử dụng cho chính class. 7
- THUỘC TÍNH CỦA LỚP Ví dụ: public class Xemay { public String nhasx; public String model; private float chiphisx; protected int thoigiansx; // so luong so cua xe may: 3, 4 protected int so; // sobanhxe là biến tĩnh có giá trị là 2 trong tất cả // các thể hiện tạo ra từ lớp xemay public static int sobanhxe = 2; } 8
- THUỘC TÍNH CỦA LỚP Lưu ý: • Thông thường để an toàn cho vùng dữ liệu của các đối tượng người ta tránh dùng tiền tố public, mà thường chọn tiền tố private để ngăn cản quyền truy cập đến vùng dữ liệu của một lớp từ các phương thức bên ngoài lớp đó. 9
- PHƯƠNG THỨC (METHOD) CỦA LỚP • Hàm hay phương thức (method) trong Java là khối lệnh thực hiện các chức năng, các hành vi xử lý của lớp lên vùng dữ liệu. Khai báo phương thức: ( ) { ; } • Để xác định quyền truy xuất của các đối tượng khác đối với các phương thức của lớp người ta thường dùng các tiền tố sau: public, protected, private, static, final, abstract, synchronized – : có thể là kiểu void, kiểu cơ sở hay một lớp. – : đặt theo qui ước giống tên biến. – : có thể rỗng 10
- PHƯƠNG THỨC (METHOD) CỦA LỚP • static: phương thức lớp dùng chung cho tất cả các thể hiện của lớp, có nghĩa là phương thức đó có thể được thực hiện kể cả khi không có đối tượng của lớp chứa phương thức đó. • final: phương thức có tiền tố này không được khai báo chồng ớ các lớp dẫn xuất. • abstract: phương thức không cần cài đặt (không có phần source code), sẽ được hiện thực trong các lớp dẫn xuất từ lớp này. • synchronized: dùng để ngăn các tác động của các đối tượng khác lên đối tượng đang xét trong khi đang đồng bộ hóa. Dùng trong lập trình multithreads. 11
- PHƯƠNG THỨC (METHOD) CỦA LỚP Ví dụ: public class Xemay { public String nhasx; public String model; private float chiphisx; protected int thoigiansx; // so luong so cua xe may: 3, 4 so protected int so; // là biến tĩnh có giá trị là 2 trong tất cả các thể hiện tạo ra từ lớp xemay public static int sobanhxe = 2; public float tinhgiaban() { return 1.5 * chiphisx; } } • Lưu ý: – Thông thường trong một lớp các phương thức nên được khai báo dùng từ khóa public, khác với vùng dữ liệu thường là dùng tiền tố private vì mục đích an toàn. – Những biến nằm trong một phương thức của lớp là các biến cục bộ (local) và nên được khởi tạo sau khi khai báo. 12
- Các biến, hằng, phương thức static 13
- Visibility Modifiers Visibility public increase protected none (no modifier) private 14
- KHỞI TẠO MỘT ĐỐI TƯỢNG • Constructor là một loại phương thức đặc biệt của lớp. • Constructor được gọi tự động khi khởi tạo một thể hiện của lớp, có thể dùng để khởi gán những giá trị măc định. • Các constructor không có giá trị trả về, và có thể có tham số hoặc không có tham số. • Constructor phải có cùng tên với lớp và được gọi đến khi dùng từ khóa new. • Nếu một lớp không có constructor thì Java sẽ cung cấp cho lớp một constructor mặc định (default constructor). Những thuộc tính, biến của lớp sẽ được khởi tạo bởi các giá trị mặc định (số: thường là giá trị 0, kiểu luận lý là giá trị false, kiểu đối tượng giá trị null, ) Lưu ý: thông thường để an toàn, dễ kiểm soát và làm chủ mã nguồn chương trình chúng ta nên khai báo một constructor cho lớp. 15
- VÍ DỤ VỀ CONSTRUCTOR public class Xemay { // public Xemay() { } public Xemay(String s_nhasx, String s_model, f_chiphisx, int i_thoigiansx, int i_so); { nhasx = s_nhasx; model = s_model; chiphisx = f_chiphisx; thoigiansx = i_thoigiansx; so = i_so; // hoặc // this.nhasx = s_nhasx; // this.model = s_model; // this.chiphisx = f_chiphisx; // this.thoigiansx = i_thoigiansx; // this.so = i_so; } 16 }
- Tham chiếu this • Biến this là một biến ẩn tồn tại trong tất cả các lớp trong ngông ngữ Java. Một class trong Java luôn tồn tại một biến this. • Biến this được sử dụng trong khi chạy và tham khảo đến bản thân lớp chứa nó. Ví dụ: class A { int ; String ; // Contructor của lớp A public A(int par_1, String par_2) { this.field_1 = par_1; this.field_2 = par_2; } () { // } () { this.method_1() // } } 17
- Tham chiếu this Dùng this để gọi một constructor khác: class Foo { private int i; public int getI() {return i;} public void setI(int i) { this.i = i; } public Foo() { this(0); } public Foo(int x) { this.i=x; } } 18
- KHAI BÁO CHỒNG PHƯƠNG THỨC • Việc khai báo trong một lớp nhiều phương thức có cùng tên nhưng khác tham số (khác kiểu dữ liệu, khác số lượng tham số) gọi là khai báo chồng phương thức (overloading method). Ví dụ: public class Xemay { // khai báo fields public float tinhgiaban() { return 2 * chiphisx; } public float tinhgiaban(float huehong) { return (2 * chiphisx + huehong); } } 19
- Nested Classes class OuterClass { class NestedClass { } } // Cần phần biệt lớp trong tĩnh, và không tĩnh class OuterClass { static class StaticNestedClass { } class InnerClass { } } 20
- Nested Classes Static Nested Classes: OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass(); Nested Classes: NestedClass1.Class2 cls2 = new NestedClass1().new Class2(); 21
- Creating an anonymous class Ví dụ: public class AnonClass { public static void main(String[] args) { Ball b = new Ball() { public void hit() { System.out.println("You hit it!"); } }; b.hit(); } interface Ball { void hit(); } } 22
- Lớp Object • Mọi lớp trong Java chỉ extends một và chỉ một lớp • Nếu ta không chỉ rõ một lớp cơ sở, lớp tạo ra sẽ tự động extends lớp Object – Mọi lớp trong Java chứa các phương thức chức năng cơ bản được định nghĩa trong lớp Object. • 3 phương thức của lớp Object thường được sử dụng: – public boolean equals(Object obj) – public int hashCode() – public String toString() 23
- Phương thức equals object1.equals(object2); • Sự thực hiện ngầm định: public boolean equals(Object obj) { return (this == obj); } • Được chồng trong các subclass để kiểm tra 2 đối tượng riêng biệt có cùng nội dung hay không. • Vd: str1.equals(str2) trong lớp String • Lưu ý khi viết phương thức chồng: Dùng equals(Object obj), not equals(Circle obj)
- public int hashCode() • Java quản lí đối tượng theo mã băm (hashCode): – Nghĩa là: địa chỉ bộ nhớ các đối tượng sẽ được “băm” (hash) theo một công thức nào đó, trở thành một số int duy nhất, không trùng lặp khi trên cùng 1 máy tính. 25
- Phương thức toString • Gọi obj.toString() trả về chuỗi biểu diễn cho đối tượng obj, ngầm định là classname@hashcode Cylinder myCyl = new Cylinder(5.0,2.0); System.out.println(myCyl.toString()); → Cylinder@15037e5 • Thường chồng phương thức toString để trả về một chuỗi dễ hiểu biểu diễn đối tượng. Vd: public String toString() { return "Cylinder length = " + length + " radius = " + getRadius(); }
- Ép kiểu đối tượng Thực hiện gán đối tượng new Student() cho một tham số kiểu Object, tương đương với 2 lệnh: Object obj = new Student(); // ép kiểu ngầm Muốn ấn định obj (kiểu Object) là một đối tượng Student: upcasting Student std = (Student) obj;//ép kiểu rõ ràng not Student std = obj; downcasting
- Autoboxing Từ Java 5: • Integer iOb = 100; // autobox an int • int i = iOb; // auto-unbox • System.out.println(i + " " + iOb); // displays 100 100 28
- Toán tử instanceof Để ép kiểu đối tượng thành công, trước đó cần chắc chắn rằng đối tượng cần ép là 1 instance của lớp tương ứng. → dùng toán tử instanceof / Giả sử myObj được khai báo kiểu Object */ / Thực hiện ép kiểu nếu myObj là 1 instance của Cylinder */ if (myObj instanceof Cylinder) { Cylinder myCyl = (Cylinder)myObj; System.out.println("The tich hinh tru la " + myCyl.findVolume(); }
- LECTURE 3 Phần 2: KẾ THỪA, ĐA HÌNH
- KẾ THỪA, GHI ĐÈ PHƯƠNG THỨC • Tính kế thừa giúp cho các lớp con nhận được các thuộc tính/phương thức public và protected của lớp cha. • Đồng thời cũng có thể thay thế các phương thức của lớp cha bằng cách khai báo ghi đè. • Lớp được kế thừa được gọi là lớp cha hoặc lớp cơ sở (superclass, base class) • Lớp kế thừa được gọi là lớp con hoặc lớp dẫn xuất (subclass, derived class) • Để khai báo lớp con kế thừa, dùng từ khóa extends class Animal{ public void move(){ System.out.println("Animals can move"); } } class Dog extends Animal{ public void move(){ System.out.println("Dogs can walk and run"); } } 31
- Overriding phương thức (tiếp) • Để ghi đè một phương thức xác định, trong subclass phải có cùng signature và cùng kiểu dữ liệu trả về với phương thức trong superclass. • Review: Các Overloading method có cùng tên, nhưng phải khác signature. • Một phương thức chỉ có thể được ghi đè chỉ khi nó có thể truy nhập được → không thể ghi đè 1 private method. • Một static method có thể được kế thừa, nhưng không thể được ghi đè.
- TIỀN TỐ TRONG KẾ THỪA Java có các tiền tố cho lớp con liên quan đến tính kế thừa của lớp: • no modifier: được truy nhập từ bất kỳ lớp nào trong cùng package, nhưng không thể từ package khác. • public: lớp có thể truy cập từ các gói, chương trình khác. • abstract: Lớp trừu tượng. 33
- Gọi Constructor của lớp cha public class SuperCircle { protected int radius; // radius co the duoc truy cap tu Sphere public SuperCircle( ) { this(0); } public SuperCircle( int radius ) { this.radius = radius; } public class SuperSphere extends SuperCircle { public SuperSphere( int rd ) { //super(rd); // Goi cau tu cua lop cha } } 34
- LỚP KHÔNG CHO PHÉP KẾ THỪA • Lớp mà ta không thể có lớp dẫn xuất từ nó (không có lớp con) gọi là lớp “vô sinh”, hay nói cách khác không thể kế thừa được từ một lớp “vô sinh”. Lớp “vô sinh” dùng để hạn chế, ngăn ngừa các lớp khác dẫn xuất từ nó. • Để khai báo một lớp là lớp “vô sinh”, chúng ta dùng từ khóa final class. • Tất cả các phương thức của lớp final đều phải là final, nhưng không yêu cầu đối với các thuộc tính. • Nếu từ khóa final đi kèm với phương thức thì phương thức đo không thể nạp chồng và ghi đè • Nếu từ khóa final đi kèm với thuộc tính thì thuộc tính đó là hằng số Ví dụ: public final class A { public final int x; private int y; public final void method_1() { // } public final void method_2() { // } } 35
- LỚPLỚP TRỪUTRỪU TƯỢNGTƯỢNG • Đôi khi một class quá trừu tượng đến mức nó không thể có instance. Nó được gọi là một abstract class. • Các abstract class có dữ liệu và phương thức tương tự như các class khác. • Không thể dùng toán tử new để tạo các đối tượng của abstract class. • header của 1 abstract class: public abstract class GeometricObject { } 36
- PHƯƠNGPHƯƠNG THỨCTHỨC TRỪUTRỪU TƯỢNGTƯỢNG • Là các phương thức chỉ có header, không có sự thực hiện (vì quá trừu tượng). • Sự thực hiện của nó được cung cấp bởi các subclass thông qua các phương thức ghi đè. • Một class có chứa ít nhất một abstract method phải là abstract class. • Ví dụ khai báo 1 abstract method: public abstract double findArea(); 37
- CÀI ĐẶT LỚP TRỪU TƯỢNG • Các lớp dẫn xuất phải cài đặt cụ thể các phương thức trừu tượng của lớp trừu tượng. Ví dụ: public class C extends A abstract class A { { abstract void method_1(); public void method_1() } { // cài đặt chi tiết cho public class B extends A { //method_1 trong lớp con C. public void method_1( ) { // // cài đặt chi tiết cho phương thức method_1 // trong lớp con B. } // } } } Lưu ý: • Các phương thức được khai báo dùng các tiền tố private và static thì không được khai báo là trừu tượng abstract. Vì, tiền tố private thì không thể truy xuất từ các lớp dẫn xuất, còn tiền tố static thì chỉ dùng riêng cho lớp khai báo mà thôi. 38
- PHƯƠNG THỨC FINALIZE • Trong java người lập trình không cần phải quá bận tâm về việc cấp phát và giải phóng vùng nhớ, sẽ có một trình dọn dẹp hệ thống đảm trách việc này. • Phương thức finalize() là một phương thức đặc biệt được cài đặt sẵn cho các lớp. Trình dọn dẹp hệ thống sẽ gọi phương thức này trước khi hủy một đối tượng. Vì vậy việc cài đặt một số thao tác giải phóng, dọn dẹp vùng nhớ đã cấp phát cho các đối tượng dữ liệu trong phương thức finalize() sẽ giúp cho người lập trình chủ động kiểm soát tốt quá trình hủy đối tượng thay vị giao cho trình dọn dẹp hệ thống tự động. • Đồng thời việc cài đặt trong phương thức finalize() sẽ giúp cho bộ nhớ được giải phóng tốt hơn, góp phần cải tiến tốc độ chương trình. Ví dụ: class A { // Khai báo các thuộc tính public void method_1( ) { // } protected void finalize() { // Có thể dùng để đóng tất cả các kết nối // vào cơ sở dữ liệu trước khi hủy đối tượng. // } 39 }
- GÓI (package) • Việc đóng gói các lớp lại tạo thành một thư viện dùng chung gọi là package. • Một package có thể chứa một hay nhiều lớp bên trong, đồng thời cũng có thể chứa một package khác bên trong. • Để khai báo một lớp thuộc một gói nào đấy ta phải dùng từ khóa package. • Dòng khai báo gói phải là dòng đầu tiên trong tập tin khai báo lớp. • Các tập tin khai báo lớp trong cùng một gói phải được lưu trong cùng một thư mục. • Lưu ý: Việc khai báo import tất cả các lớp trong gói sẽ làm tốn bộ nhớ. Thông thường chúng ta chỉ nên import những lớp cần dùng trong chương trình. Ví dụ: package phuongtiengiaothong; class Xemay { // . } class Xega extends Xemay { // } • Khi đó muốn sử dụng lớp Xemay vào chương trình ta sẽ khai báo như sau; import phuongtiengiaothong.Xemay; 40
- GIAO DIỆN (interface) Khái niệm interface: • Như chúng ta đã biết một lớp trong java chỉ có một siêu lớp trực tiếp hay một cha duy nhất (đơn thừa kế). • Để tránh đi tính phức tạp của đa thừa kế (multi-inheritance) trong lập trình hướng đối tượng, Java thay thế bằng giao tiếp (interface). • Một lớp có thể kế thừa nhiều giao diện (interface). Khai báo interface: • Interface được khai báo như một lớp. Nhưng các thuộc tính của interface là các hằng (khai báo dùng từ khóa final) và các phương thức của giao diện là trừu tượng (mặc dù không có từ khóa abstract). • Trong các lớp có cài đặt các interface ta phải tiến hành cài đặt cụ thể các phương thức này. 41
- GIAO DIỆN (interface) Ví dụ: public interface Sanpham { static final String nhasx = “Honda VN”; static final String dienthoai = “08-8123456”; public int gia(String s_model); } // khai báo 1 lớp có cài đặt interface public class Xemay implements Sanpham { // cài đặt lại phương thức của giao diện trong lớp public int gia(String s_model) { if (s_model.equals(“2005”)) return (2000); else return (1500); } public String chobietnhasx() { return (nhasx); } } 42
- GIAO DIỆN (interface) • Đa kế thừa. • Khi đó giao diện sẽ kế thừa tất cả các giá trị hằng và các phương thức của các giao diện cha. • Các giao diện cha được liệt kê thành chuỗi và cách nhau bởi dấu phẩy “,”. Khai báo như sau: public interface interfaceName extends Interface1, Interface2, Interface3 { // } 43
- Interface vs. Abstract class • Trong interface, dữ liệu phải là hằng, abstract class có thể có cả dữ liệu biến. • Trong interface, phương thức chỉ có header mà ko có thực hiện, abstract class có thể có phương thức đầy đủ. • Trong interface, tất cả dữ liệu là public final static và phương thức là public abstract. (2 cách viết sau là tương đương) public interface T1{ public interface T1{ public static final int k=1; int k=1; public abstract void p(); void p(); } } 44
- Interface vs. Abstract class • Có thể truy nhập các hằng trong interface sử dụng cú pháp InterfaceName.CONSTANT_NAME. • Có thể sử dụng interface để thực hiện đa thừa kế với class và các subinterface. public class NewClass extends BaseClass implements Interface1, , InterfaceN { } public interface NewInterface extends Interface1, , InterfaceN { // các hằng và phương thức trừu tượng } Các ví dụ về giao diện: Xemay, IT1Class 45
- Giao diện so sánh 02 đối tượng // Interface so sánh 2 đối tượng, được xác định trong java.lang package java.lang; public interface Comparable { public int compareTo(Object obj); } 46
- Đa hình thái - Polymorphism Đa hình thái: Một đối tượng của subclass có thể được sử dụng bởi bất kỳ mã lệnh nào được thiết kế để làm việc với một đối tượng của superclass. • Đa hình thái cho phép các phương thức được sử dụng chung cho một dải rộng các tham số đối tượng → generic programming. • Trong lập trình hướng đối tượng, nên lập trình theo cách dùng chung: khai báo 1 biến có kiểu superclass, nó sẽ có thể chấp nhận một giá trị của bất kỳ kiểu subclass nào.Tuy nhiên muốn vậy cần ép kiểu đối tượng. • Đa hình được thực hiện thông qua nối kết động
- Nối kết động - Dynamic binding • Việc thực hiện phương thức nào sẽ được JVM xác định khi chạy chương trình → Nối kết động. • obj là instance của các lớp c1, c2, , cn. Khi obj gọi phương thức p, thì JVM tìm sự thực hiện p trong các lớp theo thứ tự c1, c2, , cn đến khi tìm thấy.
- PHẦN 3 MỘT SỐ VÍ DỤ
- VÍ DỤ 1: VỀ TÍNH ĐA HÌNH (lớp Shape) • Sau đây là minh họa tính đa hình (polymorphism) trong phân cấp kế thừa thông qua việc mô tả và xử lý một số thao tác cơ bản trên các đối tượng hình học. // Định nghĩa lớp trừu tượng cơ sở tên Shape trong tập tin Shape.java public abstract class Shape extends Object { // trả về diện tích của một đối tượng hình học shape public double area( ) { return 0.0; } // trả về thể tích của một đối tượng hình học shape public double volume( ) { return 0.0; } // Phương thức trừu tượng cần phải được hiện thực // trong những lớp con để trả về tên đối tượng // hình học shape thích hợp public abstract String getName(); } // end class Shape 50
- VÍ DỤ 1: VỀ TÍNH ĐA HÌNH (lớp Point) Định nghĩa lớp Point trong tập tin Point.java. Lớp Point thừa kế lớp Shape public class Point extends Shape { protected int x, y; // Tọa độ x, y của 1 điểm public Point( ){ setPoint( 0, 0 ); } // constructor không tham số. public Point(int xCoordinate, int yCoordinate) // constructor có tham số. { setPoint( xCoordinate, yCoordinate ); } public void setPoint( int xCoordinate, int yCoordinate )// gán tọa độ x, y cho 1 điểm { x = xCoordinate; y = yCoordinate; } public int getX( ) { return x; } // lấy tọa độ x của 1 điểm public int getY( ) { return y; } // lấy tọa độ y của 1 điểm public String toString() // Thể hiện tọa độ của 1 điểm dưới dạng chuỗi { return "[" + x + ", " + y + "]"; } public String getName() // trả về tên của đối tượng shape { return "Point"; } } // end class Point 51
- GIẢI THÍCH (Shape và Point) • Định nghĩa một lớp cha Shape là một lớp trừu tượng dẫn xuất từ Object và có 3 phương thức khai báo dùng tiền tố public. • Phương thức getName() khai báo trừu tượng vì vậy nó phải được hiện thực trong các lớp con. • Phương thức area() (tính diện tích) và phương thức volume() (tính thể tích) được định nghĩa và trả về 0.0. • Những phương thức này sẽ được khai báo chồng trong các lớp con để thực hiện chức năng tính diện tích cũng như thể tích phù hợp với những đối tượng hình học tương ứng (đường tròn, hình trụ, ). • Lớp Point: dẫn xuất từ lớp Shape. Một điểm thì có diện tích và thể tích là 0.0, vì vậy những phương thức area() và volume() của lớp cha không cần khai báo chồng trong lớp Point, chúng được thừa kế như đã định nghĩa trong lớp trừu tượng Shape. • Những phương thức khác như setPoint( ) để gán tọa độ x, y cho một điểm, còn phương thức getX(), getY() trả về tọa độ x, y của một điểm. Phương thức getName() là hiện thực cho phương thức trừu tượng trong lớp cha, nếu như phương thức getName() mà không được định nghĩa thì 52 lớp Point là một lớp trừu tượng.
- VÍ DỤ 1: VỀ TÍNH ĐA HÌNH (lớp Circle) Định nghĩa lớp Circle trong tập tin Circle.java. Lớp Circle thừa kế lớp Point public class Circle extends Point // Dẫn xuất từ lớpPoint { protected double radius; public Circle() // constructor không tham số { // ngầm gọi đến constructor của lớp cha setRadius( 0 ); } public Circle( double circleRadius, int xCoordinate, int yCoordinate ) { // constructor có tham số // gọi constructorcủa lớp cha super( xCoordinate, yCoordinate ); setRadius( circleRadius ); } public void setRadius( double circleRadius ) // Gán bán kính của đường tròn { radius = ( circleRadius >= 0 ? circleRadius:0 ); } //còn tiếp ở slide sau 53
- VD1: VỀ TÍNH ĐA HÌNH (lớp Circle - tt) public double getRadius() // Lấy bán kính của đường tròn { return radius; } public double area() // Tính diện tích đường tròn Circle { return Math.PI * radius * radius; } public String toString() // Biểu diễn đường tròn bằng một chuỗi { return "Center = " + super.toString() + "; Radius = " + radius; } public String getName() // trả về tên của shape { return "Circle"; } } // end class Circle 54
- GIẢI THÍCH (lớp Circle) • Lớp Circle dẫn xuất từ lớp Point, một đường tròn có thể tích là 0.0, vì vậy phương thức volume() của lớp cha không khai báo chồng, nó sẽ thừa kế từ lớp Point, mà lớp Point thì thừa kế từ lớp Shape. • Diện tích đường tròn khác với một điểm, vì vậy phương thức tính diện tích area() được khai báo chồng. • Phương thức getName() hiện thực phương thức trừu tượng đã khai báo trong lớp cha, nếu phương thức getName() không khai báo trong lớp Circle thì nó sẽ kế thừa từ lớp Point. • Phương thức setRadius dùng để gán một bán kính (radius) mới cho một đối tượng đường tròn, còn phương thức getRadius trả về bán kính của một đối tượng đường tròn. 55
- VÍ DỤ 1: VỀ TÍNH ĐA HÌNH (lớp Cylinder) Định nghĩa lớp Cylinder trong tập tin Cylinder.java. Lớp Cylinder thừa kế từ lớp Circle public class Cylinder extends Circle { protected double height; // chiều cao của Cylinder public Cylinder() // constructor không có tham số { // ngầm gọi đến constructor của lớp cha setHeight( 0 ); } // constructor có tham số public Cylinder( double cylinderHeight, double cylinderRadius, int xCoordinate,int yCoordinate ) { // Gọi constructor của lớp cha super( cylinderRadius, xCoordinate, yCoordinate ); setHeight( cylinderHeight ); } //còn tiếp ở slide sau 56
- VD1: VỀ TÍNH ĐA HÌNH (lớp Cylinder-tt) public void setHeight( double cylinderHeight ) { // Gán chiều cao cho Cylinder height = ( cylinderHeight >= 0 ? cylinderHeight:0 ); } public double getHeight() // Lấy chiều cao của Cylinder { return height; } public double area() // Tính diện tích xung quanh của Cylinder { return 2 * super.area() + 2 * Math.PI * radius *height; } public double volume() // Tính thể tích của Cylinder { return super.area() * height;} public String toString() // Biểu diễn Cylinder bằng một chuỗi { return super.toString() + "; Height = " + height; } public String getName() // trả về tên của shape { return "Cylinder"; } } // end class Cylinder 57
- GIẢI THÍCH (lớp Cylinder) • Lớp Cylinder dẫn xuất từ lớp Circle. Một Cylinder (hình trụ) có diện tích và thể tích khác với một Circle (hình tròn), vì vậy cả hai phương thức area() và volume() cần phải khai báo chồng. • Phương thức getName() là hiện thực phương thức trừu tượng trong lớp cha, nếu phương thức getName() không khai báo trong lớp Cylinder thì nó sẽ kế thừa từ lớp Circle. • Phương thức setHeight dùng để gán chiều cao mới cho một đối tượng hình trụ. • Còn phương thức getHeight trả về chiều cao của một đối tượng hình trụ. 58
- VÍ DỤ 1: VỀ TÍNH ĐA HÌNH (test) File Test.java dùng để kiểm tra tính kế thừa của Point, Circle, Cylinder với lớp trừu tượng Shape. import java.text.DecimalFormat; public class Test { // Kiểm tra tính kế thừa của các đối tượng hình học public static void main( String args[] ) { // Tạo ra các đối tượng hìnhhọc Point point = new Point( 7, 11 ); Circle circle = new Circle( 3.5, 22, 8 ); Cylinder cylinder = new Cylinder( 10, 3.3, 10, 10 ); // Tạo một mảng các đối tượng hình học Shape arrayOfShapes[] = new Shape[ 3 ]; // arrayOfShapes[ 0 ] là một đối tượng Point arrayOfShapes[ 0 ] = point; // arrayOfShapes[ 1 ] là một đối tượng Circle arrayOfShapes[ 1 ] = circle; // arrayOfShapes[ 2 ] là một đối tượng cylinder arrayOfShapes[ 2 ] = cylinder; 59 //còn tiếp ở slide sau
- VÍ DỤ 1: VỀ TÍNH ĐA HÌNH (test - tt) // Lấy tên và biểu diễn của mỗi đối tượng hình học String output = point.getName() + ": " + point.toString() + "\n" + circle.getName() + ": " + circle.toString() + "\n" + cylinder.getName() + ": " + cylinder.toString(); DecimalFormat precision2 = new DecimalFormat("0.00" ); // duyệt mảng arrayOfShapes lấy tên, diện tích, thể tích // của mỗi đối tượng hình học trong mảng. for ( int i = 0; i < arrayOfShapes.length; i++ ) { output += "\n\n" + arrayOfShapes[ i ].getName() +": " + arrayOfShapes[ i].toString() +"\n Area = " + precision2.format( arrayOfShapes[ i ].area() ) +"\nVolume = " + precision2.format( arrayOfShapes[ i ].volume() ); } System.out.println(output); System.exit( 0 ); } 60 } // end class Test
- VD2: VỀ TÍNH ĐA HÌNH (interface Shape) Tương tự ví dụ 1 nhưng trong ví dụ 2 chúng ta dùng interface để định nghĩa cho Shape thay vì một lớp trừu tượng. Vì vậy tất cả các phương thức tron interface Shape phải được hiện thực trong lớp Point là lớp cài đặt trực tiếp interface Shape. // Định nghĩa một interface Shape trong tập tin shape.java public interface Shape { // Tính diện tích public abstract double area(); // Tính thể tích public abstract double volume(); // trả về tên của shape public abstract String getName(); } 61
- VD2: VỀ TÍNH ĐA HÌNH (lớp Point) Lớp Point cài đặt, hiện thực interface tên shape. Định nghĩa lớp Point trong tập tin Point.java public class Point extends Object implements Shape { protected int x, y; // Tọa độ x, y của 1 điểm public Point() // constructor không tham số. { setPoint( 0, 0 ); } public Point(int xCoordinate, int yCoordinate) // constructor có tham số. { setPoint( xCoordinate, yCoordinate ); } public void setPoint( int xCoordinate, int yCoordinate ) // gán tọa độ x, y cho 1 điểm { x = xCoordinate; y = yCoordinate; } //còn tiếp ở slide sau 62
- VD2: VỀ TÍNH ĐA HÌNH (lớp Point - tt) // lấy tọa độ x của 1 điểm public int getX() { return x; } public int getY() // lấy tọa độ y của 1 điểm { return y; } public String toString() // Thể hiện tọa độ của 1 điểm dưới dạng chuỗi { return "[" + x + ", " + y + "]"; } public double area() // Tính diện tích { return 0.0; } public double volume() // Tính thể tích { return 0.0; } public String getName() // trả về tên của đối tượng shape { return "Point"; } } // end class Point 63
- VD2: VỀ TÍNH ĐA HÌNH (lớp Circle) Lớp Circle là lớp con của lớp Point, và cài đặt/hiện thực gián tiếp interface tên shape. Định nghĩa lớp Circle trong tập tin Circle.java public class Circle extends Point { // Dẫn xuất từ lớpPoint protected double radius; public Circle() // constructor không tham số { // ngầm gọi đến constructor của lớp cha setRadius( 0 ); } // constructor có tham số public Circle( double circleRadius, int xCoordinate, int yCoordinate ) { // gọi constructorcủa lớp cha super( xCoordinate, yCoordinate ); setRadius( circleRadius ); } //còn tiếp ở slide sau 64
- VD2: VỀ TÍNH ĐA HÌNH (lớp Circle - tt) public void setRadius( double circleRadius ) // Gán bán kính của đường tròn { radius = ( circleRadius >= 0 ? circleRadius:0 ); } public double getRadius() // Lấy bán kính của đường tròn { return radius; } public double area() // Tính diện tích đường tròn Circle { return Math.PI * radius * radius; } public String toString() // Biểu diễn đường tròn bằng một chuỗi { return "Center = " + super.toString() + "; Radius = " + radius; } // trả về tên của shape public String getName() { return "Circle"; } } // end class Circle 65
- VD2: VỀ TÍNH ĐA HÌNH (lớp Cylinder) Định nghĩa lớp hình trụ Cylinder trong tập tin Cylinder.java. public class Cylinder extends Circle { protected double height; // chiều cao của Cylinder public Cylinder() // constructor không có tham số { // ngầm gọi đến constructor của lớp cha setHeight( 0 ); } // constructor có tham số public Cylinder( double cylinderHeight, double cylinderRadius, int xCoordinate,int yCoordinate ) { // Gọi constructor của lớp cha super( cylinderRadius, xCoordinate,yCoordinate ); setHeight( cylinderHeight ); } public void setHeight( double cylinderHeight ) // Gán chiều cao cho Cylinder { height = ( cylinderHeight >= 0 ? cylinderHeight:0 ); } //còn tiếp ở slide sau 66
- VD2: VỀ TÍNH ĐA HÌNH (lớp Cylinder-tt) public double getHeight() // Lấy chiều cao của Cylinder { return height; } public double area() // Tính diện tích xung quanh của Cylinder { return 2 * super.area() + 2 * Math.PI * radius * height; } public double volume() // Tính thể tích của Cylinder { return super.area() * height; } public String toString() // Biểu diễn Cylinder bằng một chuỗi { return super.toString() + "; Height = " + height; } // trả về tên của shape public String getName() { return "Cylinder"; } } // end class Cylinder 67
- VD2: VỀ TÍNH ĐA HÌNH (test) Tập tin Test.java để kiểm tra tính kế thừa của Point, Circle, Cylinder với interface Shape. import java.text.DecimalFormat; public class Test // Kiểm tra tính kế thừa của các đối tượng hình học { public static void main( String args[] ) { // Tạo ra các đối tượng hìnhhọc Point point = new Point( 7, 11 ); Circle circle = new Circle( 3.5, 22, 8 ); Cylinder cylinder = new Cylinder( 10, 3.3, 10, 10 ); Shape arrayOfShapes[] = new Shape[ 3 ]; // Tạo một mảng các đối tượng hình học // arrayOfShapes[ 0 ] là một đối tượng Point arrayOfShapes[ 0 ] = point; arrayOfShapes[ 1 ] = circle; // arrayOfShapes[ 1 ] là một đối tượng Circle arrayOfShapes[ 2 ] = cylinder; // arrayOfShapes[ 2 ] là một đối tượng cylinder // Lấy tên và biểu diễn của mỗi đối tượng hình học String output = point.getName() + ": " + point.toString() + "\n" + circle.getName() + ": " + circle.toString() + "\n“ + cylinder.getName() + ": " + cylinder.toString(); DecimalFormat precision2 = new DecimalFormat("0.00" ); //còn tiếp ở slide sau 68
- VD2: VỀ TÍNH ĐA HÌNH (test - tt) // duyệt mảng arrayOfShapes lấy tên, diện tích, thể tích // của mỗi đối tượng hình học trong mảng. for ( int i = 0; i < arrayOfShapes.length; i++ ) { output += "\n\n" + arrayOfShapes[ i ].getName() + ": " + arrayOfShapes[ i].toString() + "\n Area = " + precision2.format( arrayOfShapes[ i ].area() ) + "\nVolume = " + precision2.format( arrayOfShapes[ i ].volume() ); } System.out.println(output); System.exit( 0 ); } } // end class Test 69