Wednesday, July 4, 2007

Tìm hiểu lập trình hướng đối tượng (OOP) - 5

Ta lại tiếp tục chủ đề hướng đối tượng với khái niệm tham chiếu, copy đối tượng
Từ các phần trước ta đã biết qua các khái niệm lớp, đối tượng, và các cách làm viêc với chúng
Trong phần này ta sẽ tìm hiểu về hoạt động của đối tượng
Xét lớp sau




package test1;

public class ClassA {
private String field;

/**
* @return the field
*/
public String getField() {
return field;
}

/**
* @param field the field to set
*/
public void setField(String field) {
this.field = field;
}
}



Khi chúng ta khởi tạo một đối tượng thông qua toán tử new

ClassA objA = new ClassA();

Hệ thống sẽ cung cấp một vùng nhớ tương ứng với lớp ClassA, và vùng nhớ này sẽ được trỏ đến bởi tham chiếu objA
Sau đó

objA.setField("field 1");

thì giá trị "field 1" sẽ được lưu vào vùng nhớ đã được cấp thông qua tham chiếu objA

System.out.println("1. a: " + a.getField()); sẽ cho kết quả là 1.a : field 1

Với một khởi tạo khác

ClassA objB = new ClassA();

Hệ thống sẽ tiếp tục cung cấp một vùng nhớ tương ứng với lớp ClassA và vùng này sẽ được trỏ đến bởi tham chiếu objB
Nếu ta tiếp tục thao tác như trên thì không có gì xảy ra, nhưng giả sử ta thực hiện như sau

objB = objA;
hoặc ClassA objB = objA;

thì khi này hệ thống không cung cấp vùng nhớ để tham chiếu objB trỏ vào mà hệ thống sẽ cho tham chiếu objB trỏ vào vùng nhớ mà tham chiếu objA đã trỏ vào. Và khi đó, 2 tham chiếu objA, objB sẽ có chung một vùng nhớ, những thay đổi từ 2 tham chiếu này sẽ được đưa vào vùng nhớ trênm và sẽ 'ảnh hưởng' lẫn nhau


ClassA objA = new ClassA();
objA.setField("field 1");
ClassA objB = objA;

System.out.println("1. a: " + objA.getField()); => 1. a: field 1
System.out.println("1. b: " + objB.getField()); => 1. b: field 1

objA.setField("field 2");
System.out.println("2. a: " + objA.getField()); => 2. a: field 2
System.out.println("2. b: " + objB.getField()); => 2. b: field 2

objB.setField("field 3");
System.out.println("3. a: " + objA.getField()); => 3. a: field 3
System.out.println("3. b: " + objB.getField()); => 3. b: field 3


Như vậy toán tử new sẽ khởi tạo vùng nhớ mới cho đối tượng, và toán tử = chỉ đơn giản là cùng trỏ hai tham chiếu vào cùng một vùng nhớ chứ không mang tính copy hoàn toàn đối tượng

Như vậy, với lớp ClassA ta có thể viết tiếp một phương thức copy 'bản thân' nó thành một đối tượng mới như sau


package test1;

public class ClassA {
private String field;

/**
* @return the field
*/
public String getField() {
return field;
}

/**
* @param field the field to set
*/
public void setField(String field) {
this.field = field;
}

public ClassA clone(){
ClassA obj = new ClassA();
obj.setField(this.field);
return obj;
}
}




Phương thức clone() sẽ copy hoàn toàn một đối tượng hiện tại


ClassA objA = new ClassA();
objA.setField("field 1");
ClassA objB = objA;
ClassA objC = objA.clone();

System.out.println("1. a: " + objA.getField()); => 1. a: field 1
System.out.println("1. b: " + objB.getField()); => 1. b: field 1
System.out.println("1. c: " + objC.getField()); => 1. c: field 1

objA.setField("field 2");
System.out.println("2. a: " + objA.getField()); => 2. a: field 2
System.out.println("2. b: " + objB.getField()); => 2. b: field 2
System.out.println("2. c: " + objC.getField()); => 2. c: field 1

objB.setField("field 3");
System.out.println("3. a: " + objA.getField()); => 3. a: field 3
System.out.println("3. b: " + objB.getField()); => 3. b: field 3
System.out.println("3. c: " + objC.getField()); => 3. c: field 1

No comments:

Post a Comment