oop 8

22
Bài 8: Giao diện và tính đa hình Giảng viên: Nguyễn Thị Minh Huyền [email protected] Đỗ Thanh Hà [email protected]

Upload: thai-hoc-vu

Post on 29-Jun-2015

729 views

Category:

Education


0 download

DESCRIPTION

slide java o lop

TRANSCRIPT

Page 1: Oop 8

Bài 8: Giao diện và tính đa hình

Giảng viên: Nguyễn Thị Minh Huyề[email protected]

Đỗ Thanh Hà[email protected]

Page 2: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 2

Tài liệu tham khảo BigJava – chương 11

Page 3: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 3

Tái sử dụng mã chương trình (1)

Xét ví dụ DataSet.java (ch07/input) Tìm giá trị trung bình và giá trị lớn nhất

của 1 tập các giá trị số Phải làm gì nếu muốn tìm trị trung bình và lớn

nhất của 1 tập các tài khoản ngân hàng (BankAccount, ch08)?

Hay muốn tìm loại tiền xu có giá trị cao nhất trong 1 tập các loại tiền xu (Coin, bài 6)?

Page 4: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 4

Tái sử dụng mã chương trình (2)

public class DataSet // Modified for BankAccount objects { . . .

public void add(BankAccount x) { sum = sum + x.getBalance(); if (count == 0 || maximum.getBalance() < x.getBalance())

maximum = x; count++;

} public BankAccount getMaximum() {

return maximum; } private double sum; private BankAccount maximum; private int count;

}

Page 5: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 5

Tái sử dụng mã chương trình (3)

public class DataSet // Modified for Coin objects { . . .

public void add(Coin x) { sum = sum + x.getValue(); if (count == 0 || maximum.getValue() < x.getValue())

maximum = x; count++;

} public Coin getMaximum() {

return maximum; } private double sum; private Coin maximum; private int count;

}

Page 6: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 6

Tái sử dụng mã chương trình (4)

Các ví dụ trên có chung cơ chế phân tích dữ liệu, chỉ khác nhau về độ đo dữ liệu Các lớp liên quan có thể thống nhất 1 phương thức getMeasure

để thu được giá trị đo dùng trong quá trình phân tích Khi đó có thể cài 1 lớp duy nhất DataSet có thể sử dụng chung,

trong đó phần thân của phương thức add có dạng:

sum = sum + x.getMeasure(); if (count == 0 || maximum.getMeasure() < x.getMeasure())

maximum = x; count++;

Kiểu của biến x là gì? x cần phải tham chiếu tới bất kì lớp nào có hàm getMeasure.

Page 7: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 7

Tái sử dụng mã chương trình (5) Để mô tả các lớp có chung một số thao tác nào đó

(như getMeasure), trong Java người ta khai báo một kiểu giao diện (interface) đặc tả các thao tác chung đó public interface Measurable {

double getMeasure();}

Khai báo interface liệt kê danh sách các nguyên mẫu phương thức (prototype) mà kiểu giao diện cần có

Các lớp có chung giao diện này sẽ cài đặt (implements) cụ thể các phương thức đặc tả trong kiểu giao diện.

Page 8: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 8

Lớp DataSet dùng chung cho các đối tượng đo được

public class DataSet { . . .

public void add(Measurable x) { sum = sum + x.getMeasure(); if (count == 0 || maximum.getMeasure() < x.getMeasure())

maximum = x; count++;

} public Measurable getMaximum() {

return maximum; } private double sum; private Measurable maximum; private int count;

}

Page 9: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 9

Cài đặt một kiểu giao diện Để khai báo 1 lớp cài đặt 1 kiểu giao diện, dùng

từ khoá implements public class BankAccount implements Measurable {

public double getMeasure() { return balance;

} // Additional methods and fields

} 1 lớp có thể cài đặt nhiều kiểu giao diện

Khi cài đặt 1 kiểu giao diện, lớp đó phải định nghĩa tất cả các phương thức đã đặc tả trong kiểu giao diện

Page 10: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 10

Cú pháp Định nghĩa 1 kiểu giao diện

public interface InterfaceName { // method signatures

} Tất cả các phương thức trong kiểu giao diện đều

đương nhiên là public Cài đặt 1 kiểu giao diện

public class ClassName implements InterfaceName, InterfaceName, ... {

// interface method implementations // other methods // instance variables

} VD: Xem các lớp trong ch11/measure1

Page 11: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 11

Sơ đồ UML (1) Sử dụng kiểu giao diện có thể giúp giảm tính

móc nối giữa các lớp Kí hiệu UML:

Kiểu giao diện được đánh dấu bằng nhãn «interface»

Mũi tên nét đứt với mũi hình tam giác kí hiệu quan hệ “is-a” giữa 1 lớp và 1 giao diện

Mũi tên nét đứt với mũi hình chữ v mở kí hiệu quan hệ “uses” hay quan hệ phụ thuộc

Page 12: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 12

Sơ đồ UML (2)

VD

Page 13: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 13

Chuyển đổi kiểu giữa lớp và giao diện

Có thể chuyển 1 kiểu lớp về 1 kiểu giao diện, với điều kiện lớp cài đặt giao diện BankAccount account = new BankAccount(10000);

Measurable x = account; // OK Ngược lại, để chuyển 1 kiểu giao diện về 1 kiểu lớp phải

thực hiện ép kiểu DataSet coinData = new DataSet();

coinData.add(new Coin(0.25, "quarter"));coinData.add(new Coin(0.1, "dime"));. . .// Get the largest coin Measurable max = coinData.getMaximum(); String name = max.getName(); // ERRORCoin maxCoin = (Coin) max;String name = maxCoin.getName();

Page 14: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 14

Tính đa hình Biến kiểu giao diện dùng để chứa tham chiếu tới đối

tượng của 1 lớp cài đặt giao diện đó Measurable x;x = new BankAccount(10000);x = new Coin(0.1, "dime");

Có thể gọi bất kì phương thức nào của kiểu giao diện với tham biến ẩn x Tuỳ theo x đang tham chiếu tới đối tượng thuộc lớp nào thì áp

dụng phương thức cài đặt trong lớp đó => tính đa hình Gọi là liên kết muộn (late binding): khi chạy chương trình mới xác

định dùng phương thức của lớp nào Khác với liên kết sớm (early binding): chương trình dịch xác định

dùng phương thức nào trong các phương thức cùng tên

Page 15: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 15

Sử dụng kiểu giao diện cho gọi lại (callback)

Nhược điểm của kiểu giao diện Measurable: Chỉ dùng được giao diện này để đo trong các lớp thuộc quyền của

người lập trình Chỉ đo/đánh giá được đối tượng theo 1 tiêu chí

VD với 1 tài khoản tiết kiệm không thể vừa đo theo số tiền trong tài khoản, vừa đo theo lãi suất

Cơ chế gọi lại (callback): cho phép 1 lớp gọi tới 1 phương thức đặc trưng tuỳ theo thông tin cần khai thác

Xét lớp DataSet Trong VD trước, việc đo 1 đối tượng do 1 phương thức của đối

tượng đó đảm nhiệm Thay cho cách làm đó, dùng 1 phương thức đo có tham biến hiện

là đối tượng cần đo

Page 16: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 16

Sử dụng kiểu giao diện cho gọi lại (2)

Muốn vậy: Định nghĩa kiểu giao diệnpublic interface Measurer {

double measure(Object anObject); } Định nghĩa phương thức add trong DataSetpublic void add(Object x) {

sum = sum + measurer.measure(x); if (count == 0 || measurer.measure(maximum)

< measurer.measure(x)) maximum = x; count++;

}

Page 17: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 17

Sử dụng kiểu giao diện cho gọi lại (3)

Cài đặt giao diện Measurer:public class RectangleMeasurer implements Measurer {

public double measure(Object anObject) {Rectangle aRectangle = (Rectangle) anObject;

double area = aRectangle.getWidth()*aRectangle.getHeight();

return area; }

} Sử dụng DataSet:

Measurer m = new RectangleMeasurer();DataSet data = new DataSet(m);data.add(new Rectangle(5, 10, 20, 30));data.add(new Rectangle(10, 20, 30, 40));. . .

Page 18: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 18

Sơ đồ UML

Xem chương trình ch11/measure2

Page 19: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 19

Lớp trong (inner classes) Có thể định nghĩa 1 lớp đơn giản bên trong 1 phương thức

Lớp này chỉ dùng được trong phương thức VD (ch11/measure3)

public class DataSetTester3 { public static void main(String[] args) {

class RectangleMeasurer implements Measurer { . . .

} Measurer m = new RectangleMeasurer();

DataSet data = new DataSet(m); . . .

} }

Chương trình dịch sẽ tạo ra 1 tệp riêng cho lớp trong DataSetTester3$1RectangleMeasurer.class

Nếu 1 lớp được định nghĩa trong 1 lớp khác nhưng ngoài các phương thức của lớp đó thì có thể dùng được lớp đó trong mọi phương thức của lớp ấy.

Page 20: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 20

Ví dụ minh hoạ: Xử lí sự kiện đếm thời gian

javax.swing.Timer sinh các sự kiện đếm thời gian cách đều nhau, hữu dụng khi cần cập nhật 1 đối tượng trong 1 khoảng thời gian đều đặn

Cách dùng (Xem ch11/timer1): Định nghĩa 1 lớp MyListener cài đặt kiểu giao diện ActionListener: gửi sự kiện

tới bộ nghe public interface ActionListener {     void actionPerformed(ActionEvent event);}

class MyListener implements ActionListener {   void actionPerformed(ActionEvent event){      // This action will be executed at each timer event      Place listener action here   }}

Tạo đối tượng Timer với bộ nghe đã cài đặt MyListener listener = new MyListener();Timer t = new Timer(interval, listener);t.start();

Page 21: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 21

Truy cập các biến xung quanh (1)

Các phương thức của 1 lớp trong có thể truy cập các biến định nghĩa trong phạm vi xung quanh Hữu dụng khi cài đặt các bộ điều khiển sự kiện VD: Làm hình động – di chuyển 1 hình 10 lần trong 1s

class Mover implements ActionListener { public void actionPerformed(ActionEvent event) {

// Move the rectangle }

} ActionListener listener = new Mover(); final int DELAY = 100; // Milliseconds between timer ticks Timer t = new Timer(DELAY, listener); t.start();

Page 22: Oop 8

2009-2010 OOP - http://mim.hus.edu.vn/elearning 22

Truy cập các biến xung quanh (2)

Phương thức actionPerformed có thể truy cập các biến trong phạm vi xung quanh (ch11/timer2):

public static void main(String[] args) { . . . final Rectangle box = new Rectangle(5, 10, 20, 30); class Mover implements ActionListener {

public void actionPerformed(ActionEvent event) { // Move the rectangle box.translate(1, 1);

} } . . .

} Các biến địa phương muốn truy cập được bởi lớp trong phải được khai

báo là final Lớp trong có thể truy cập trường dữ liệu của đối tượng thuộc lớp ngoài 1 đối tượng thuộc lớp trong được tạo trong 1 phương thức tĩnh chỉ có

thể truy cập các trường dữ liệu tĩnh