Lập trình Java toàn tập_P6: Innerclasses_Generic

Inner class là lớp được định nghĩa trong lớp khác và không thể tồn tại độc lập. Nó có thể truy xuất tới mọi thuộc tính và phương thức của lớp ngoài (kể cả private)

ppt27 trang | Chia sẻ: diunt88 | Lượt xem: 3275 | Lượt tải: 1download
Bạn đang xem trước 20 trang tài liệu Lập trình Java toàn tập_P6: Innerclasses_Generic, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Innerclasses Inner class Inner class là lớp được định nghĩa trong lớp khác và không thể tồn tại độc lập. Nó có thể truy xuất tới mọi thuộc tính và phương thức của lớp ngoài (kể cả private) Cú pháp của Inner class Local inner class Lớp được định nghĩa bên trong 1 phương thức của lớp khác. Định nghĩa lớp được xem như 1 đoạn lệnh Cú pháp của local inner class Anonymous inner class Lớp được khai báo mà không có tên, bên trong 1 đoạn lệnh Các thuộc tính, hàm của nó chỉ được truy xuất ngay tại vị trí nó định nghĩa. Cú pháp Anonymous inner class Quyền truy xuất – modifiers Có thể sử dụng các modifier như lớp bên ngoài: public, private, protected, package-private Generic Nguyễn Thị Tú Mi Email: nttmi@hcmuaf.edu.vn Lập trình Generic Lập trình theo kiểu Generic có nghĩa là lập trình mà có thể tái sử dụng cho nhiều kiểu dữ liệu. Lập trình Generic cho phép bạn trừu tượng hóa kiểu dữ liệu Lập trình Generic từ trước JDK1.5 Dựa trên khái niệm kế thừa public class ArrayList { public Object get(int i) { . . . } public void add(Object o) { . . . } . . . private Object[] elementData; } Lập trình Generic từ trước JDK1.5 Hạn chế: Phải ép kiểu  ép sai kiểu Không kiểm soát được kiểu dữ liệu trên 1 collection ArrayList names = new ArrayList(); . . . String filename = (String) names.get(0); List myList = new ArrayList(); myList.add("Fred"); myList.add(new Dog()); myList.add(new Integer(42)); Lập trình Generic Cho phép chỉ định kiểu dữ liệu của các Collection  hạn chế việc nhập sai kiểu dữ liệu. Không cần ép kiểu dữ liệu List myList = new ArrayList(); myList.add("Fred"); // OK, it will hold Strings myList.add(new Dog()); //compiler error! String s = myList.get(0); Lập trình Generic for (String s : myList) { int x = s.length(); // no need for a cast before calling a // String method! The compiler already knew // "s" was a String coming from MyList } void takeListOfstrings(List strings) { strings.add("foo"); // no problem adding a String } void takeListOfStrings(List strings) { strings.add(new Integer(42)); // NO!! strings is type safe } Ví dụ của generic public interface List { void add(E x); Iterator iterator(); } public interface Iterator { E next(); boolean hasNext(); } Tính đa hình và Generic Liệu ta có thể lập trình như thế này: class Parent { } class Child extends Parent { } List myList = new ArrayList(); Câu trả lời??? Tính đa hình và Generic A: Không, trình biên dịch sẽ báo lỗi Luật Generic: Kiểu bạn khai báo generic phải cùng với kiểu của các đối tượng thực sự. Nếu bạn đã khai báo List  Các đối tượng là cha hoặc con của lớp Foo sẽ không được chấp nhận. Tính đa hình và Generic Các trường hợp Generic sai: List myList = new ArrayList(); // NO! List numbers = new ArrayList(); // NO! // remember that Integer is a subtype of Number Các trường hợp đúng: List myList = new ArrayList(); // yes List myList = new ArrayList(); // yes List myList = new ArrayList(); // yes Ghi chú Ghi chú: Các kiểu dữ liệu nguyên thủy không được phép generic Chỉ được generic trên các đối tượng (kể cả các lớp bao của các đối tượng nguyên thủy: Integer, Float…) Wildcards Bạn có thể dùng dấu ? để hiển thị cho một kiểu dữ liệu chưa biết trong collection void printCollection(Collection c) { for (Object e : c) { System.out.println(e); }} Khi biên dịch, dấu ? có thể được thay thế bởi bất kì kiểu dữ liệu nào. Wildcards Tuy nhiên bạn viết như thế này là không hợp lệ Collection c = new ArrayList(); c.add("a1"); //compile error, null Vì bạn không biết c đại diện cho tập hợp kiểu dữ liệu nào  không thể thêm phần tử vào c Bounded Wildcards Bạn thiết kế chương trình như sau: public abstract class Shape { public abstract void draw(Canvas c); } public class Circle extends Shape { private int x, y, radius; public void draw(Canvas c) { ... } } public class Rectangle extends Shape { private int x, y, width, height; public void draw(Canvas c) { ... } } public class Canvas { public void draw(Shape s) { s.draw(this); } } public void drawAll(List shapes) { for (Shape s: shapes) { s.draw(this); } } Bạn chỉ được vẽ trên 1 danh sách shape cụ thể nào đó. VD: circle Bounded Wildcards Sửa lại để vẽ được danh sách của bất kì Shape nào public void drawAll(List shapes) { ... } Generic methods Như bạn đã biết Làm sao để chỉ 1 đối tượng chưa biết mà vẫn thao tác trên đối tượng đó static void fromArrayToCollection(Object[] a, Collection c) { for (Object o : a) { c.add(o); // compile time error }} static void fromArrayToCollection(T[] a, Collection c) { for (T o : a) { c.add(o); // correct }} Ví dụ interface Collection { public boolean containsAll(Collection c); public boolean addAll(Collection c); } interface Collection { public boolean containsAll(Collection c); public boolean addAll(Collection c); // hey, type variables can have bounds too! } class Collections { public static void copy(List dest, List src){...} } class Collections { public static void copy(List dest, List src){...} } Type Parameter Conventions — Type — for Type, được sử dụng khi T đã được dùng — Element (được dùng trong Java Collections Framework) Summary
Tài liệu liên quan