Làm việc với mảng đối tượng
Giải thích được:
Thừa kế là gì trong OOP.
Các loại thừa kế trong các ngôn ngữOOP.
Đa hình là gì trong OOP.
Phân biệt được kỹ thuật Overloading và overriding.
Hiện thực được đặc điểm thừa kế trong OOP với Java.
Hiện thực được đặc điểm đa hình trong OOP với Java.
Sử dụng được toán tử instanceOf và ép kiểu trong Java
Giải thích được những tình huống có thể xẩy ra khi ép kiểu.
Giải thích được loại tham số trong hàm của Java.
16 trang |
Chia sẻ: haohao89 | Lượt xem: 2732 | Lượt tải: 3
Bạn đang xem nội dung tài liệu Bài giảng Tính kế thừa và đa hình, để tải tài liệu về máy bạn click vào nút DOWNLOAD ở trên
1TÍNH KẾ THỪA VÀ ĐA HÌNH
INHERITANCE - POLYMORPHISM
2
Ôn tập
Accsess modifier: chỉ thị mức độ cho phép bên ngoài truy
cập vào một dữ liệu hay một hành vi của 1 lớp.
Khi thiết kế 1 lớp: Các yếu tố sau cần được xem xét để
chọn access modifier phù hợp.
Constructor: Hành vi được thực thi ngay lúc khởi tạo đối
tượng.
Tập các constructor tạo ra tập các mẫu khởi tạo biến đối
tượng.
Một đối tượng sống từ lúc đối tượng được khởi tạo (bằng
new) cho đến khi khối chứa nó được thực thi xong.
Phạm vi của 1 đối tượng là vùng văn bản chương trình từ
lúc định nghĩa biến đến hết khối chứa biến này.
Destructor: Hành vi được thực thi vào lúc đối tượng chết (
Java không hỗ trợ destructor).
3
Đặc tính truy xuất
Modifier private friendly protected public
Cùng class YES YES YES YES
Cùng gói, khác
class
NO YES NO YES
lớp con trong cùng
gói với lớp cha
NO YES YES YES
Khác gói, khác lớp NO NO NO YES
Lớp con khác gói
với lớp cha
NO NO YES YES
4
Mục tiêu
Làm việc với mảng đối tượng
Giải thích được:
Thừa kế là gì trong OOP.
Các loại thừa kế trong các ngôn ngữ OOP.
Đa hình là gì trong OOP.
Phân biệt được kỹ thuật Overloading và overriding.
Hiện thực được đặc điểm thừa kế trong OOP với Java.
Hiện thực được đặc điểm đa hình trong OOP với Java.
Sử dụng được toán tử instanceOf và ép kiểu trong Java
Giải thích được những tình huống có thể xẩy ra khi ép kiểu.
Giải thích được loại tham số trong hàm của Java.
5
Nội dung
Mảng đối tượng
Lớp ArrayList
Thành phần static
Chỉ thị final
Tính kế thừa – Inheritance.
Superclass và Supclass
Các loại thừa kế.
Hiện thực lớp con trong Java.
Từ khóa super
Tính đa hình.
Kỹ thuật Overriding
Quan hệ qiữa các lớp
Toán tử instanceof
Vấn đề ép kiểu trong Java
Tham số của hàm trong Java
6
Mảng các đối tượng
Các phần tử của một mảng có thể là những tham chiếu đối
tượng
String[] words = new String[10];
HinhChuNhat[] arr_hcn = new HinhChuNhat[5];
Ngay khi khởi tạo, một mảng đối tượng giữ các tham chiếu
null
Mỗi một đối tượng lưu trữ trong một mảng phải được tạo riêng
biệt nhau
words object stores 10 references to String objects
arr_hcn object stores 5 references to HinhChuNhat objects
7Mảng các đối tượng
Mảng words ngay khi được khai báo:
words -
-
-
-
-
Ngay tại thời điểm này, tham chiếu dưới đây sẽ đưa
ra một NullPointerException:
System.out.println (words[0]);
8
Mảng các đối tượng
Sau khi một vài đối tượng String được tạo và được lưu trữ
trong mảng:
“friendship”words
-
-
“loyalty”
“honor”
Words[0] = new String(“friendship”);
Words[1] = new String(“loyalty”);
Words[2] = new String(“honor”);
9
Mảng các đối tượng
Sau khi một vài đối tượng HinhChuNhat được tạo và được
lưu trữ trong mảng:
(5,4)arr_hcn
-
-
(7,3)
(100,50)
arr_hcn[0] = new HinhChuNhat(5,4);
arr_hcn[1] = new HinhChuNhat(7,3);
arr_hcn[2] = new HinhChuNhat(100,50);
10
Ví dụ - Mảng các đối tượng
Một sơ đồ UML cho chương trình MainHCN:
MainHCN
+ main (args : String[]) : void
HinhChuNhatCollection
- collection : HinhChuNhat[]
- count : int
+ addHinhChuNhat (cd : double, cr :
double) : void
+ toString() : String
- increaseSize() : voidHinhChuNhat- cdai : double
- crong : double
+ toString() : String
*
1
•Xem HinhChuNhat
•Xem Array_HinhChuNhat
•Xem MainHCN
11
Bài tập - Mảng các đối tượng
Mô hình UML cho chương trình Tunes:
Tunes
+ main (args : String[]) :
void
CDCollection
- collection : CD[]
- count : int
- totalCost : double
+ addCD (title : String, artist : String,
cost : double, tracks : int) : void
+ toString() : String
- increaseSize() : voidCD
- title : String
- artist : String
- cost : double
- tracks : int
+ toString() : String
*
1
12
Lớp ArrayList
Lớp ArrayList đặt trong gói java.util
Giống như mảng, đối tượng ArrayList có thể lưu trữ danh
sách các giá trị và tham chiếu, mỗi phần tử sử dụng một số
chỉ mục (index)
Tuy nhiên, chúng ta có thể sử dụng cú pháp dấu ngoặc đơn
(bracket) với một đối tượng ArrayList.
Đối tượng ArrayList tăng và giảm kích thước khi cần thiết,
điều chỉnh dung lượng của nó khi cần thiết.
Khai báo:
ArrayList name = new ArrayList();
13
Lớp ArrayList
Những phần tử được thêm vào hoặc xóa đi thông qua việc gọi
một phương thức của lớp.
Khi một phần tử trong mảng được thêm vào thì những phần
tử khác “di chuyển sang một bên" để tạo khoảng trống
Tương tự như vậy, khi một phần tử được xóa đi, danh sach
“thu bớt" để đóng khoảng trống
Chỉ mục của các phần tử được điều chỉnh cho phù hợp
Một vài phương thức của lớp ArrayList:
14
Những phương thức của lớp ArrayList
ArrayList()
Constructor: creates an initially empty list.
boolean add (Object obj)
Inserts the specified object to the end of this list.
void add (int index, Object obj)
Inserts the specified object into this list at the specified index.
void clear()
Removes all elements from this list.
Object remove (int index)
Removes the element at the specified index in this list and returns it.
Object get (int index)
Returns the object at the specified index in this list without removing it.
int indexOf (Object obj)
Returns the index of the first occurrence of the specified object.
boolean contains (Object obj)
Returns true if this list contains the specified object.
boolean isEmpty()
Returns true if this list contains no elements.
int size()
Returns the number of elements in this list.
15
Beatles.java
import java.util.ArrayList;
public class Beatles
{
public static void main (String[] args)
{ ArrayList band = new ArrayList();
band.add ("Paul");
band.add ("Pete");
band.add ("John");
band.add ("George");
System.out.println (band);
int location = band.indexOf ("Pete");
band.remove (location);
System.out.println (band);
System.out.println ("At index 1: " + band.get(1));
band.add (2, "Ringo");
System.out.println ("Size of the band: " + band.size());
} } 16
Lớp ArrayList
Một ArrayList được phép lưu trữ bất kỳ kiểu đối tượng nào.
Chúng ta cũng có thể định nghĩa một đối tượng ArrayList
để chấp nhận một kiểu đối tượng cụ thể
Ví dụ:
ArrayList alName = new ArrayList();
ArrayList alHT = new ArrayList();
17
Vòng lặp ArrayList
Ví dụ
for (HinhChuNhat h : arrHCN)
{
System.out.println(“Chu vi la:” + h.ChuVi());
System.out.println(“Dien tich la:” + h.DienTich());
}
for (Object o : arraylistName)
{
// process o
}
18
Ví dụ - Mảng các đối tượng ArrayList
Một sơ đồ UML cho chương trình MainHCN:
MainHCN
+ main (args : String[]) :
void
HinhChuNhatCollection
- collection : HinhChuNhat[]
- count : int
+ addHinhChuNhat (cd : double, cr :
double) : void
+ toString() : StringHinhChuNhat
- cdai : double
- crong : double
+ toString() : String
*
1
• Xem ArrayList_HinhChuNhat
• Xem MainHCN
19
Bài tập - Mảng các đối tượng ArrayList
Mô hình UML cho chương trình Tunes:
Tunes
+ main (args : String[]) :
void
CDCollection
- collection : ArrayList
- count : int
- totalCost : double
+ addCD (ID: String,title : String, artist :
String): boolean
cost : double, tracks : int) : void
+ toString() : String
+ DeleteCD(ID:String): boolean
+ FindCD(ID: String): CD
CD
- ID : String
- title : String
- artist : String
- cost : double
- tracks : int
+ toString() : String
*
1
20
Thành phần static
Đôi khi ta muốn một dữ liệu, một đoạn code, một hành vi là
toàn cục để trongmột lớp Dùng chỉ thị static.
Dữ liệu static là DỮ LIỆU TOÀN CỤC.
Hành vi static là hành vi toàn cục
Code static là CODE TOÀN CỤC và chỉ thao tác lên dữ
liệu static.
Truy xuất dữ liệu và code này thông qua tên lớp hoặc một
đối tượng thuộc lớp có thành phần static.
(1) ClassName.StaticMember
(2) ClassName obj= new ClassName();
obj. StaticMember
21
Dữ liệu static- Thí dụ
Truy xuất static data bằng tên lớp
Truy xuất static data bằng tên đối tượng thuộc lớp
22
Ví dụ - Hành vi static
Nhận xét
Hành vi static được bên ngoài sử
dụng mà không cần khai báo biến
đối tượng thuộc lớp. Do vậy, hành
vi static thường có tham số không
liên quan đến đối tượng thuộc lớp.
23
Ví dụ - Code static
Cú pháp đưa một đoạn code static:
static
{
}
Code static được thực thi ngay khi lớp có code này được tham chiếu tới.
24
Ví dụ - Code static
Code static chỉ tham chiếu dữ liệu static
25
Ví dụ - Code static
Nếu có nhiều đoạn code static,
các đoạn code này được thực thi tuần tự
26
Code static với constructor
tham chiếu khi chưa có đối tượng
tham chiếu khi đã có đối tượng
Vì khi có đối tượng, constructor
có code làm thay đổi trị của n
nên kết qủa đã khác đi.
27
Chỉ thị final
Làm sao để không cho phép kế thừa từ một lớp ( lớp không
con).
Làm sao không cho phép sửa một dữ liệu ( muốn dữ liệu là
hằng).
Dùng chỉ thị final
28
final Data là hằng cấm sửa
29
final class là lớp không con
30
final method là hành vi không cho phép lớp con viết lại (override)
Phương thức final
31
Tính kế thừa – Inheriatance
Lập trình hướng đối tượng cho phép bạn phát triển những
lớp mới từ các lớp đã tồn tại.
Khả năng một lớp thừa hưởng data và code từ một hay
nhiều lớp khác.
Kỹ thuật giúp tái sử dụng code Tiết kiệm công sức lập
trình, công sức kiểm tra code.
Vd: lớp B được phát triển từ lớp A:
A
B
B inherits A
32
Superclass và Subclass
Vd: lớp B được phát triển từ lớp A:
B: subclass, extended class, derived class
A: superclass, parent class, base class
Subclass thừa kế từ superclass các trường dữ liệu và
phương thức có thể truy xuất được, và cũng có thể thêm
vào các trường dữ liệu và phương thức mới.
33
Superclass và Subclass (tiếp)
Thực tế, subclass thường được mở rộng để chứa nhiều
thông tin chi tiết và nhiều chức năng hơn so với superclass
của nó.
Circle Cylinder1 TestCylinder1
34
Tính kế thừa- Inheritance
ID_Num
Name
YearOfBirth
Address
getID_Num()
setID_Num(newID)
......
class PERSON
RollNum
Score
getScore()
setSore(newScore)
......
class STUDENT
quan hệ
“is a”
Chỉ phải
hiện thực
bằng này
Để được cái
tương đương
ID_Num
Name
YearOfBirth
Address
getID_Num()
setID_Num(newID)
......
class STUDENT
RollNum
Score
getScore()
setSore(newScore)
......
thừa
kế
tính
chất
riêng
Con = Cha + một tí
35
Kỹ thuật phân cấp thừa kế
(1) Liệt kê đặc điểm của các đối tượng cần quan tâm.
(2) Tìm tập giao của các tính chất giữa các lớp, tách tập giao này để
xây dựng lớp cha.
(3) Đặt 1 tên gọi có ý nghĩa cho lớp cha.
(4) Phần còn lại sau khi tách tập giao là các lớp con.
36
Các loại thừa kế.
Đơn thừa kế
Đa thừa kế ( thừa kế bội)
Mỗi ngôn ngữ OOP hỗ trợ khả năng thừa kế riêng.
C++ : đa thừa kế.
C# , Java : Đơn thừa kế
37
Hiện thực thừa kế trong Java.
class CLASSNAME extends FATHERCLASSNAME
{ DataType1 Property1 [=Value];
DataType2 Property1 [=Value];
CLASSNAME (DataType Arg,…) // constructor
{… }
[Modifier] DataType MethodName(DataType Arg,…)
{ … }
}
Lớp con là mở rộng
của lớp cha
Từ khóa dùng
trong thừa kế
38
Ví dụ
Cylinder kế thừa Circle
Circle
Cylinder
39
Ví dụ
Circle
- radius: double
+ Circle ()
+ Circle (r : double)
+ getRadius() : double
+ setRadius(r : double) : void
+ findArea() : double
Cylinder
- length: double
+ Cylinder()
+ Cylinder (r : double, l : double)
+ getLength() : double
+ setLength (l : double) : void
+ findVolume() : double
TestCylinder
+ main (args : String[]) : void
Sơ đồ lớp cho
TestCylinder
40
Circle.java
public class Circle
{
private double radius;
public Circle()
{
radius = 1.0;
}
public Circle (double r)
{
radius = r;
}
public double getRadius()
{
return radius;
}
public void setRadius (double r)
{
radius = r;
}
public double findArea()
{
return radius*radius*Math.PI;
}
}
Circle
- radius: double
+ Circle ()
+ Circle (r : double)
+ getRadius() : double
+ setRadius(r : double) : void
+ findArea() : double
41
Cylinder.java
public class Cylinder extends Circle
{
private double length;
public Cylinder()
{
radius = 1.0;
length = 1.0;
}
public Cylinder (double r, double l)
{
radius = r;
length = l;
}
public double getLength()
{
return length;
}
public void setLength (double l)
{
length = l;
}
public double findVolume()
{
return findArea()*length;
}
}
Cylinder
- length: double
+ Cylinder()
+ Cylinder (r : double, l : double)
+ getLength() : double
+ setLength (l : double) : void
+ findVolume() : double
Error, setRadius(1.0)
Error, setRadius(r)
42
TestCylinder.java
public class TestCylinder
{
public static void main (String[] args)
{
Cylinder c = new Cylinder (5.0, 5.2);
System.out.println(“The radius is “ + c.getRadius());
System.out.println(“The length is “ + c.getLength());
System.out.println(“The area of the circle is “ + c.findArea());
System.out.println(“The volume of the cylinder is “ + c.findVolume());
}
}
43
Sử dụng từ khóa super
super được dùng để thay cho superclass, tương tự như
this thay cho đối tượng được gọi.
Dùng super để:
- gọi 1 constructor của superclass
- gọi 1 phương thức của superclass
- gọi 1 biến thuộc tính của superclass
44
Gọi Superclass Constructor
super(), hoặc super(tham_số)
Lệnh trên phải được đặt tại dòng đầu tiên trong constructor
của subclass và là cách duy nhất để gọi 1 constructor của
superclass.
public Cylinder() {
}
public Cylinder() {
super();
}
45
Gọi thành viên của Superclass
super.tên_phương_thức(tham_số)
super.tên_biến thuộc_tính
Vd:
- double findVolume() {
return super.findArea() * length;
}
46100
emp
mng
p
200
300
P01
Hoa
21
P02
Luan
25
150
P03
Quang
25
150
200
100
200
300
Ví dụ
47
Bổ từ truy xuất
public
protected
none (no modifier)
private
Visibility
increase
public class C1 {
public int x;
protected int y ;
int z;
private int u;
protected void m () {
}
}
public class C2 {
C1 o = new C1();
can access o.x;
can access o.y;
can access o.z;
cannot access o .u;
can invoke o.m();
}
public class C3
extends C1 {
can access x;
can access y;
can access z;
cannot access u ;
can invoke m();
}
public class C4
extends C1 {
can access x;
can access y;
cannot access z ;
cannot access u ;
can invoke m();
}
public class C5 {
C1 o = new C1();
can access o.x;
cannot access o .y;
cannot access o .z;
cannot access o .u;
cannot invoke o .m();
}
package p 1;
package p 2;
48
private và protected modifiers
Sử dụng private để ẩn hoàn toàn các thành phần của
class (dữ liệu, phương thức), chúng sẽ không thể được truy
xuất trực tiếp từ bên ngoài lớp.
Sử dụng protected để cho phép các thành phần của
class được truy xuất 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.
49
public và default modifiers
Sử dụng default modifier (no modifier) thì các thành phần
của class được truy xuất từ bất kỳ lớp nào trong cùng
package, nhưng không thể từ package khác.
Sử dụng public cho phép các thành phần của class có
thể được truy xuất 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.
50
Chú ý
Các ký hiệu -, #, + được sử dụng để biểu diễn tương ứng
các modifier private, protected, và public.
Khi chồng phương thức:
Nếu phương thức trong superclass là protected thì có
thể thay đổi phương thức chồng trong subclass thành
public.
Nhưng nếu phương thức trong superclass là public thì
phương thức chồng trong subclass bắt buộc cũng phải
là public.
51
Ví dụ 1
Circle
# radius : double
+ Circle()
+ Circle(r : double)
+ getRadius() : double
+ setRadius(r : double) : void
+ Area() : double
Cylinder
- length : double
+ Cylinder()
+ Cylinder (r : double, l : double)
+ getLength() : double
+ setLength (l : double) : void
+ Volume() : double
TestCylinder
+ main (args : String[]) : void
Sơ đồ lớp cho TestCylinder
52
Circle.java
public class Circle
{
protected double radius;
public Circle()
{
radius = 1.0;
}
public Circle (double r)
{
radius = r;
}
public double getRadius()
{
return radius;
}
public void setRadius (double r)
{
radius = r;
}
public double Area()
{
return radius*radius*Math.PI;
}
}Circle
# radius : double
+ Circle()
+ Circle(r : double)
+ getRadius() : double
+ setRadius(r : double) : void
+ Area() : double
53
Cylinder.java
public class Cylinder extends
Circle
{
private double length;
public Cylinder()
{
//super();
radius=1.0;
length = 1.0;
}
public Cylinder (double r,double l)
{
//super (r);
radius=r;
length = l;
}
public double getLength()
{
return length;
}
public void setLength (double l)
{
length = l;
}
public double Volume()
{
return super.Area() * length;
}
}
Cylinder
- length : double
+ Cylinder()
+ Cylinder(r : double, l : double)
+ getLength() : double
+ setLength(l : double) : void
+ Volume() : double
54
Ví dụ 2
Book2
# pages : int
+ Book (numPages : int)
+ setPages (numPages : int): void
+ getPage() : int
Dictionary2
- definitions : int
+ Dictionary (numPages: int, numDefinitions: int)
+ computeRatio() : double
+ setDefinitions (numDefinitions : int) : void
+ getDefinitions() : int
Words2
+ main (args : String[]) : void
55
Book2.java
public class Book2
{
protected int pages;
public Book2 (int numPages)
{
pages = numPages;
}
public void setPages (int numPages)
{
pages = numPages;
}
public int getPages ()
{
return pages;
}
}
Book2
# pages : int
+ Book (numPages : int)
+ setPages (numPages : int): void
+ getPage() : int
56
Dictionary2.java
public class Dictionary2 extends Book2
{
private int definitions;
public Dictionary2 (int numPages, int numDefinitions)
{
super(numPages);
definitions = numDefinitions;
}
public double computeRatio ()
{
return definitions/super.pages;
}
public void setDefinitions (int numDefinitions)
{
definitions=numDefinitions;
}
public int getDefinitions ()
{
return definitions;
}
}
Dictionary2
- definitions : int
+ Dictionary (numPages: int, numDefinitions: int)
+ computeRatio() : double
+ setDefinitions (numDefinitions : int) : void
+ getDefinitions() : int
57
Words2.java
public class Words2
{
public static void main (String[] args)
{
Dictionary2 w = new Dictionary2 (1500, 52500);
System.out.println ("Number of pages: " + w.getPages());
System.out.println ("Number of definitions: " +
w.getDefinitions());
System.out.println ("Definitions per page: " +
w.computeRatio());
}
}
58
Bài tập
Nguoi
# SoCNMD: String
# HoTen: String
# NgaySinh: String ( hoặc Date)
# Diachi: String
+ Nguoi (SoCMND, Hoten, Ngaysinh, Diachi)
+ setCMND (SoCMND : String): void
+ getCMND() : String
+ setHoten (Hoten : String): void
+ getHoten() : String
+ setNgaysinh (Ngaysinh : String): void
+ getNgaysinh() : String
+ setDiachi(Diachi : String): void
+ getDiachi() : String
SinhVien
- MSSV : String
- DiemLT, DiemTH: double
+ setDiemLT(diemLT: double)
+ setDiemTH(diemLH: double)
+ DiemTB () : double
+ toString : String
+ SinhVien(MaSV, Hoten, SoCMND, Diachi,
Ngaysinh, DiemLT, DiemTH)
Test_Student
+ main (args : String[]) : void
59
Bài tập
Phân tích phân cấp thừa kế cho các lớp:
Hàng điện máy <mã hàng, tên hàng, nhà sản xuất, giá, thời
gian bảo hành, điện áp, công suất>
Hàng sành sứ < mã hàng, tên hàng, nhà sản xuất, giá, loại
nguyên liệu>
Hàng thực phẩm <mã hàng, tên hàng, nhà sản xuất, giá,
ngày sản xuất, ngày hết hạn dùng>
Viết chương trình tạo mỗi loại một mặt hàng cụ thể. xuất
thông tin về các mặt hàng này.
Gợi ý: cách viết tương tự ví dụ trên.
60
Tính đa hình - Polymorphism
Đa hình thái, nhiều cách phản ứng khác nhau cho cùng một
hành vi.
Lớp A có hành vi M().
Lớp B là con của lớp A, trong lớp B viết lại hành vi M().
Có biến đối tượng o