Khi nào bạn muốn hai tham chiếu đến cùng một đối tượng?


20

Trong Java cụ thể, nhưng cũng có khả năng trong các ngôn ngữ khác: khi nào có ích khi có hai tham chiếu đến cùng một đối tượng?

Thí dụ:

Dog a = new Dog();
Dob b = a;

Có một tình huống mà điều này sẽ hữu ích? Tại sao đây sẽ là một giải pháp ưa thích để sử dụng abất cứ khi nào bạn muốn tương tác với đối tượng được đại diện bởi a?


Đó là bản chất đằng sau mô hình Flykg .

@MichaelT Bạn có thể giải thích?
Bassinator

7
Nếu ab luôn luôn tham chiếu giống nhau Dog, thì không có điểm nào cho nó. Nếu họ đôi khi có thể, thì nó khá hữu ích.
Gabe

Câu trả lời:


45

Một ví dụ là khi bạn muốn có cùng một đối tượng trong hai danh sách riêng biệt :

Dog myDog = new Dog();
List dogsWithRabies = new ArrayList();
List dogsThatCanPlayPiano = new ArrayList();

dogsWithRabies.add(myDog);
dogsThatCanPlayPiano.add(myDog);
// Now each List has a reference to the same dog

Một cách sử dụng khác là khi bạn có cùng một đối tượng đóng một số vai trò :

Person p = new Person("Bruce Wayne");
Person batman = p;
Person ceoOfWayneIndustries = p;

4
Tôi xin lỗi nhưng tôi tin rằng đối với ví dụ Bruce Wayne của bạn có một lỗ hổng thiết kế, vị trí người dơi và ceo nên có vai trò cho người của bạn.
Silviu Burcea

44
-1 để tiết lộ danh tính bí mật của Batman.
Ampt

2
@Silviu Burcea - Tôi hoàn toàn đồng ý ví dụ Bruce Wayne không phải là một ví dụ hay. Một mặt, nếu một chỉnh sửa văn bản toàn cầu đã thay đổi tên 'ceoOfWayneInustries' và 'batman' thành 'p' (giả sử không có xung đột về tên hoặc thay đổi phạm vi), và ngữ nghĩa của chương trình đã thay đổi, thì đó là một cái gì đó bị hỏng. Đối tượng được tham chiếu đại diện cho ý nghĩa thực sự, không phải tên biến trong chương trình. Để có các ngữ nghĩa khác nhau, nó là một đối tượng khác nhau hoặc được tham chiếu bởi một cái gì đó có nhiều hành vi hơn một tham chiếu (cần phải trong suốt), và do đó không phải là một ví dụ về 2+ tài liệu tham khảo.
xe cứu thương

2
Mặc dù ví dụ Bruce Wayne như được viết có thể không hoạt động, tôi tin rằng ý định đã nêu là đúng. Có lẽ một ví dụ gần hơn có thể là Persona batman = new Persona("Batman"); Persona bruce = new Persona("Bruce Wayne"); Persona currentPersona = batman;- nơi bạn có nhiều giá trị có thể (hoặc danh sách các giá trị khả dụng) và tham chiếu đến giá trị hiện đang hoạt động / được chọn.
Dan Puzey

1
@gbulmer: Tôi sẽ khẳng định rằng bạn không thể có một tham chiếu đến hai đối tượng; các tham chiếu currentPersonatrỏ đến một đối tượng này hoặc đối tượng khác, nhưng không bao giờ cả hai. Đặc biệt, nó có thể dễ dàng có thể currentPersonađược bao giờ thiết lập để bruce, trong trường hợp này nó chắc chắn không phải là một tham chiếu đến hai đối tượng. Tôi muốn nói rằng, trong ví dụ của tôi, cả hai batmancurrentPersonađều là các tham chiếu đến cùng một thể hiện, nhưng phục vụ các ý nghĩa ngữ nghĩa khác nhau trong chương trình.
Dan Puzey

16

Đó thực sự là một câu hỏi sâu sắc đáng ngạc nhiên! Kinh nghiệm từ C ++ hiện đại (và các ngôn ngữ lấy từ C ++ hiện đại, như Rust) cho thấy rằng rất thường xuyên, bạn không muốn điều đó! Đối với hầu hết dữ liệu, bạn muốn một tham chiếu duy nhất hoặc duy nhất ("sở hữu"). Ý tưởng này cũng là một lý do chính cho các hệ thống loại tuyến tính .

Tuy nhiên, ngay cả khi đó bạn thường muốn một số tài liệu tham khảo "mượn" ngắn được sử dụng để truy cập bộ nhớ một cách nhanh chóng nhưng không tồn tại trong một phần đáng kể thời gian dữ liệu tồn tại. Thông thường nhất khi bạn chuyển một đối tượng làm đối số cho một hàm khác (Tham số cũng là biến!):

void encounter(Dog a) {
  hissAt(a);
}

void hissAt(Dog b) {
  // ...
}

Một trường hợp ít phổ biến hơn khi bạn sử dụng một trong hai đối tượng tùy thuộc vào một điều kiện, thực hiện cùng một việc bất kể bạn chọn:

Dog a, b;
Dog goodBoy = whoseAGoodBoy ? a : b;
feed(goodBoy);
walk(goodBoy);
pet(goodBoy);

Quay trở lại sử dụng phổ biến hơn, nhưng để lại các biến cục bộ phía sau, chúng tôi chuyển sang các trường: Ví dụ: các widget trong khung GUI thường có các widget mẹ, vì vậy khung lớn của bạn chứa mười nút sẽ có ít nhất mười tham chiếu trỏ đến nó (cộng thêm một số từ cha mẹ của nó và có lẽ từ người nghe sự kiện và như vậy). Bất kỳ loại biểu đồ đối tượng và một số loại cây đối tượng (những loại có tham chiếu cha / anh chị em), có nhiều đối tượng tham chiếu đến từng đối tượng giống nhau. Và hầu như mọi tập dữ liệu thực sự là một biểu đồ ;-)


3
"Trường hợp ít phổ biến hơn" khá phổ biến: bạn có các đối tượng được lưu trữ trong danh sách hoặc bản đồ, truy xuất đối tượng bạn muốn và thực hiện các thao tác cần thiết. Bạn không xóa các tài liệu tham khảo của họ khỏi bản đồ hoặc danh sách.
SJuan76

1
@ SJuan76 "trường hợp ít phổ biến hơn" chỉ đơn thuần là lấy từ các biến cục bộ, mọi thứ liên quan đến cấu trúc dữ liệu đều nằm dưới điểm cuối cùng.

Đây có phải là lý tưởng của chỉ một tham chiếu do quản lý bộ nhớ đếm tham chiếu? Nếu vậy, điều đáng nói là động lực không liên quan đến các ngôn ngữ khác với các trình thu gom rác khác nhau (ví dụ: C #, Java, Python)
MarkJ

@MarkJ Các loại tuyến tính không chỉ là một mã lý tưởng, nhiều mã hiện có vô tình phù hợp với nó bởi vì đó là điều đúng về mặt ngữ nghĩa đối với khá nhiều trường hợp. Nó có lợi thế về hiệu suất tiềm năng (nhưng không phải để đếm tham chiếu cũng như truy tìm các GC, nó chỉ giúp ích khi bạn sử dụng một chiến lược khác thực sự khai thác kiến ​​thức đó để bỏ qua cả đếm và truy tìm). Thú vị hơn là ứng dụng của nó để quản lý tài nguyên đơn giản, mang tính quyết định. Hãy suy nghĩ ngữ nghĩa di chuyển RAII và C ++ 11, nhưng tốt hơn (áp dụng thường xuyên hơn và lỗi được trình biên dịch bắt gặp).

6

Biến tạm thời: xem xét mã giả sau.

Object getMaximum(Collection objects) {
  Object max = null;
  for (Object candidate IN objects) {
    if ((max is null) OR (candidate > max)) {
      max = candidate;
    }
  }
  return max;
}

Các biến maxcandidatecó thể trỏ đến cùng một đối tượng, nhưng phép gán biến thay đổi bằng các quy tắc khác nhau và tại các thời điểm khác nhau.


3

Để bổ sung các câu trả lời khác, bạn cũng có thể muốn đi qua một cấu trúc dữ liệu khác nhau, bắt đầu từ cùng một nơi. Ví dụ: nếu bạn có một BinaryTree a = new BinaryTree(...); BinaryTree b = a, bạn có thể đi qua con đường ngoài cùng bên trái của cây với avà con đường ngoài cùng bên phải của nó bbằng cách sử dụng một cái gì đó như:

while (!a.equals(null) && !b.equals(null)) {
    a = a.left();
    b = b.right();
}

Đã được một thời gian kể từ khi tôi viết Java, do đó mã có thể không chính xác hoặc hợp lý. Lấy nó nhiều hơn như mã giả.


3

Phương pháp này rất tuyệt khi bạn có một vài đối tượng mà tất cả gọi lại cho một đối tượng khác có thể được sử dụng theo cách không theo văn bản.

Ví dụ: nếu bạn có giao diện theo thẻ, bạn có thể có Tab1, Tab2 và Tab3. Bạn cũng có thể muốn có thể sử dụng một biến chung cho dù người dùng đang sử dụng tab nào để đơn giản hóa mã của bạn và giảm việc phải tìm hiểu xem người dùng của bạn đang sử dụng tab nào.

Tab Tab1 = new Tab();
Tab Tab2 = new Tab();
Tab Tab3 = new Tab();
Tab CurrentTab = new Tab();

Sau đó, trong mỗi tab được đánh số trên Click, bạn có thể thay đổi CurrentTab để tham chiếu Tab đó.

CurrentTab = Tab3;

Bây giờ trong mã của bạn, bạn có thể gọi "CurrentTab" mà không cần biết bạn đang thực sự sử dụng Tab nào. Bạn cũng có thể cập nhật các thuộc tính của CurrentTab và chúng sẽ tự động chảy xuống Tab được tham chiếu.


3

Có rất nhiều tình huống trong đó b phải là một tham chiếu đến một "" không xác định ađể có ích. Đặc biệt:

  • Bất cứ lúc nào bạn không biết những bđiểm nào vào thời gian biên dịch.
  • Bất cứ lúc nào bạn cần lặp đi lặp lại qua một bộ sưu tập, cho dù có biết vào thời gian biên dịch hay không
  • Bất cứ lúc nào bạn có phạm vi giới hạn

Ví dụ:

Thông số

public void DoSomething(Thing &t) {
}

t là một tham chiếu đến một biến từ một phạm vi bên ngoài.

Trả về giá trị và các giá trị có điều kiện khác

Thing a = Thing.Get("a");
Thing b = Thing.Get("b");
Thing biggerThing = Thing.max(a, b);
Thing z = a.IsMoreZThan(b) ? a : b;

biggerThingzlà mỗi tài liệu tham khảo cho một trong hai ahoặc b. Chúng tôi không biết cái nào vào thời gian biên dịch.

Lambdas và giá trị trả về của họ

Thing t = someCollection.FirstOrDefault(x => x.whatever > 123);

xlà một tham số (ví dụ 1 ở trên) và tlà giá trị trả về (ví dụ 2 ở trên)

Bộ sưu tập

indexByName.add(t.name, t);
process(indexByName["some name"]);

index["some name"]là, ở một mức độ lớn, một cái nhìn tinh vi hơn b. Đó là bí danh cho một đối tượng được tạo và nhồi vào bộ sưu tập.

Vòng lặp

foreach (Thing t in things) {
 /* `t` is a reference to a thing in a collection */
}

t là một tham chiếu đến một mục được trả về (ví dụ 2) bởi một trình vòng lặp (ví dụ trước).


Ví dụ của bạn rất khó để làm theo. Đừng hiểu lầm tôi, tôi đã vượt qua họ, nhưng tôi phải làm việc với nó. Trong tương lai, tôi khuyên bạn nên tách các ví dụ mã của bạn thành các khối riêng lẻ (với một số ghi chú giải thích cụ thể từng khối), không đặt một vài ví dụ không liên quan trong một khối.
Bassinator

1
@HCBPshenanigans Tôi không mong bạn thay đổi câu trả lời đã chọn; nhưng, tôi đã cập nhật thông tin của mình để hy vọng giúp đọc và điền vào một số trường hợp sử dụng bị thiếu trong câu trả lời đã chọn.
Svidgen

2

Đó là một điểm rất quan trọng, nhưng IMHO đáng để hiểu.

Tất cả các ngôn ngữ OO luôn tạo các bản sao của tài liệu tham khảo và không bao giờ sao chép một đối tượng 'vô hình'. Sẽ khó hơn nhiều để viết chương trình nếu các ngôn ngữ OO hoạt động theo bất kỳ cách nào khác. Ví dụ, các hàm và phương thức, không bao giờ có thể cập nhật một đối tượng. Java và hầu hết các ngôn ngữ OO sẽ gần như không thể sử dụng nếu không có độ phức tạp được thêm vào đáng kể.

Một đối tượng trong một chương trình được cho là có ý nghĩa. Ví dụ, nó đại diện cho một cái gì đó cụ thể trong thế giới vật lý thực. Nó thường có ý nghĩa để có nhiều tài liệu tham khảo cho cùng một điều. Ví dụ: địa chỉ nhà của tôi có thể được cung cấp cho nhiều người và tổ chức và địa chỉ đó luôn đề cập đến cùng một vị trí thực tế. Vì vậy, điểm đầu tiên là, các đối tượng thường đại diện cho một cái gì đó cụ thể, thực tế hoặc cụ thể; và vì vậy việc có thể có nhiều tài liệu tham khảo cho cùng một điều là vô cùng hữu ích. Nếu không sẽ khó hơn để viết chương trình.

Mỗi khi bạn chuyển alàm đối số / tham số cho hàm khác, ví dụ như gọi
foo(Dog aDoggy);
hoặc áp dụng một phương thức a, mã chương trình bên dưới sẽ tạo một bản sao của tham chiếu, để tạo tham chiếu thứ hai cho cùng một đối tượng.

Hơn nữa, nếu mã có tham chiếu được sao chép nằm trong một luồng khác nhau, thì cả hai có thể được sử dụng đồng thời để truy cập vào cùng một đối tượng.

Vì vậy, trong hầu hết các chương trình hữu ích, sẽ có nhiều tham chiếu đến cùng một đối tượng, bởi vì đó là ngữ nghĩa của hầu hết các ngôn ngữ lập trình OO.

Bây giờ, nếu chúng ta nghĩ về nó, bởi vì chuyển qua tham chiếu là cơ chế duy nhất có sẵn trong nhiều ngôn ngữ OO (C ++ hỗ trợ cả hai), chúng ta có thể mong đợi nó là hành vi mặc định 'đúng' .

IMHO, sử dụng tài liệu tham khảo là mặc định đúng , vì một vài lý do:

  1. Nó đảm bảo rằng giá trị của một đối tượng được sử dụng ở hai nơi khác nhau là như nhau. Hãy tưởng tượng việc đặt một đối tượng vào hai cấu trúc dữ liệu khác nhau (mảng, danh sách, v.v.) và thực hiện một số thao tác trên một đối tượng thay đổi nó. Đó có thể là một cơn ác mộng để gỡ lỗi. Quan trọng hơn, đó cùng một đối tượng trong cả hai cấu trúc dữ liệu hoặc chương trình có lỗi.
  2. Bạn có thể vui vẻ cấu trúc lại mã thành một số hàm hoặc hợp nhất mã từ một số hàm thành một và ngữ nghĩa không thay đổi. Nếu ngôn ngữ không cung cấp ngữ nghĩa tham chiếu, việc sửa đổi mã sẽ còn phức tạp hơn nữa.

Ngoài ra còn có một đối số hiệu quả; tạo bản sao của toàn bộ các đối tượng là ít hiệu quả hơn so với sao chép một tài liệu tham khảo. Tuy nhiên, tôi nghĩ rằng bỏ lỡ điểm. Nhiều tham chiếu đến cùng một đối tượng có ý nghĩa hơn và dễ sử dụng hơn, vì chúng phù hợp với ngữ nghĩa của thế giới thực.

Vì vậy, IMHO, thường có ý nghĩa khi có nhiều tham chiếu đến cùng một đối tượng. Trong các trường hợp bất thường khi điều đó không có ý nghĩa trong ngữ cảnh của thuật toán, hầu hết các ngôn ngữ đều cung cấp khả năng tạo bản sao 'bản sao' hoặc bản sao sâu. Tuy nhiên đó không phải là mặc định.

Tôi nghĩ rằng những người tranh luận rằng điều này không nên là mặc định đang sử dụng ngôn ngữ không cung cấp bộ sưu tập rác tự động. Ví dụ, C ++ lỗi thời. Vấn đề ở đây là họ cần tìm cách thu thập các vật thể 'chết' và không đòi lại các vật thể vẫn có thể được yêu cầu; có nhiều tài liệu tham khảo cho cùng một đối tượng làm cho điều đó trở nên khó khăn.

Tôi nghĩ rằng, nếu C ++ có bộ sưu tập rác đủ chi phí thấp, để tất cả các đối tượng được tham chiếu là rác được thu thập, thì phần lớn sự phản đối sẽ biến mất. Vẫn sẽ có một số trường hợp trong đó ngữ nghĩa tham chiếu không phải là những gì cần thiết. Tuy nhiên, theo kinh nghiệm của tôi, những người có thể xác định những tình huống đó cũng thường có khả năng chọn ngữ nghĩa phù hợp.

Tôi tin rằng có một số bằng chứng cho thấy một lượng lớn mã trong chương trình C ++ có sẵn để xử lý hoặc giảm thiểu việc thu gom rác. Tuy nhiên, viết và duy trì loại mã 'cơ sở hạ tầng' đó làm tăng thêm chi phí; nó ở đó để làm cho ngôn ngữ dễ sử dụng hơn hoặc mạnh mẽ hơn. Vì vậy, ví dụ, ngôn ngữ Go được thiết kế tập trung vào việc khắc phục một số điểm yếu của C ++ và nó không có lựa chọn nào khác ngoài bộ sưu tập rác.

Điều này tất nhiên không liên quan trong bối cảnh của Java. Nó cũng được thiết kế để dễ sử dụng và bộ sưu tập rác cũng vậy. Do đó, có nhiều tài liệu tham khảo là ngữ nghĩa mặc định và tương đối an toàn theo nghĩa các đối tượng không được thu hồi trong khi có một tài liệu tham khảo cho chúng. Tất nhiên chúng có thể được giữ bởi một cấu trúc dữ liệu vì chương trình không được dọn dẹp đúng cách khi nó thực sự kết thúc với một đối tượng.

Vì vậy, xoay quanh câu hỏi của bạn (với một chút khái quát), khi nào bạn muốn có nhiều hơn một tham chiếu đến cùng một đối tượng? Khá nhiều trong mọi tình huống tôi có thể nghĩ ra. Chúng là ngữ nghĩa mặc định của hầu hết các cơ chế truyền tham số ngôn ngữ. Tôi đề nghị đó là bởi vì ngữ nghĩa mặc định của việc xử lý các đối tượng tồn tại trong thế giới thực khá nhiều phải được tham chiếu ('vì các đối tượng thực tế ở ngoài đó).

Bất kỳ ngữ nghĩa khác sẽ khó xử lý hơn.

Dog a = new Dog("rover");  // initialise with name 
DogList dl = new DogList()
dl.add(a)
...
a.setOwner("Mr Been")

Tôi đề nghị rằng "rover" trong dlnên được thực hiện bởi setOwnerhoặc các chương trình khó viết, hiểu, gỡ lỗi hoặc sửa đổi. Tôi nghĩ rằng hầu hết các lập trình viên sẽ bối rối hoặc mất tinh thần nếu không.

Sau đó, con chó được bán:

soldDog = dl.lookupOwner("rover", "Mr Been")
soldDog.setOwner("Mr Mcgoo")

Loại xử lý này là phổ biến và bình thường. Vì vậy, ngữ nghĩa tham chiếu là mặc định bởi vì nó thường có ý nghĩa nhất.

Tóm tắt: Luôn có ý nghĩa khi có nhiều tham chiếu đến cùng một đối tượng.


điểm tốt, nhưng điều này phù hợp hơn như là một nhận xét
Bassinator

@HCBPshenanigans - Tôi nghĩ rằng điểm này có thể quá ngắn gọn và không được trả lời quá nhiều. Vì vậy, tôi đã mở rộng về lý luận. Tôi nghĩ rằng đó là một câu trả lời 'meta' cho câu hỏi của bạn. Tóm tắt, nhiều tham chiếu đến cùng một đối tượng là rất quan trọng để làm cho các chương trình dễ viết vì nhiều đối tượng trong một chương trình đại diện cho các trường hợp cụ thể hoặc duy nhất của sự vật trong thế giới thực.
xe cứu thương

1

Tất nhiên, một kịch bản khác mà bạn có thể kết thúc với:

Dog a = new Dog();
Dog b = a;

là khi bạn đang duy trì mã và btừng là một con chó khác, hoặc một lớp khác, nhưng bây giờ được phục vụ bởi a.

Nói chung, trong trung hạn, bạn nên làm lại tất cả các mã để tham khảo atrực tiếp, nhưng điều đó có thể không xảy ra ngay lập tức.


1

Bạn muốn điều này bất cứ lúc nào chương trình của bạn có cơ hội kéo một thực thể vào bộ nhớ ở nhiều vị trí, có thể vì các thành phần khác nhau đang sử dụng nó.

Bản đồ nhận dạng đã cung cấp một cửa hàng thực thể cục bộ dứt khoát để chúng tôi có thể tránh có hai hoặc nhiều đại diện riêng biệt. Khi chúng tôi đại diện cho cùng một đối tượng hai lần, khách hàng của chúng tôi có nguy cơ gây ra sự cố đồng thời nếu một tham chiếu của đối tượng vẫn tồn tại thay đổi trạng thái của nó trước khi đối tượng khác thực hiện. Ý tưởng là chúng tôi muốn đảm bảo rằng khách hàng của chúng tôi luôn xử lý tham chiếu dứt khoát đến thực thể / đối tượng của chúng tôi.


0

Tôi đã sử dụng điều này khi viết một bộ giải Sudoku. Khi tôi biết số lượng ô khi xử lý các hàng, tôi muốn cột chứa cũng biết số của ô đó khi xử lý các cột. Vì vậy, cả cột và hàng là mảng của các đối tượng ô trùng nhau. Chính xác như câu trả lời được chấp nhận cho thấy.


-2

Trong các ứng dụng web, Trình tạo đối tượng quan hệ có thể sử dụng tải lười biếng để tất cả các tham chiếu đến cùng một đối tượng cơ sở dữ liệu (ít nhất là trong cùng một luồng) trỏ đến cùng một điều.

Ví dụ: nếu bạn có hai bảng:

Chó:

  • id | chủ sở hữu_id | Tên
  • 1 | 1 | Bark Kent

Chủ sở hữu:

  • id | Tên
  • 1 | tôi
  • 2 | bạn

Có một số cách tiếp cận mà ORM của bạn có thể thực hiện nếu các cuộc gọi sau được thực hiện:

dog = Dog.find(1)  // fetch1
owner = Owner.find(1) // fetch2
superdog = owner.dogs.first() // fetch3
superdog.name = "Superdog"
superdog.save! // write1
owner = dog.owner // fetch4
owner.name = "Mark"
owner.save! // write2
dog.owner = Owner.find(2)
dog.save! // write3

Trong chiến lược ngây thơ, tất cả các cuộc gọi đến các mô hình và các tham chiếu liên quan đều lấy các đối tượng riêng biệt. Dog.find(), Owner.find(), owner.dogs, Và dog.ownerkết quả trong một cơ sở dữ liệu đánh lần đầu tiên xung quanh, sau đó họ sẽ được lưu vào bộ nhớ. Và như vậy:

  • cơ sở dữ liệu được tìm nạp từ ít nhất 4 lần
  • dog.owner không giống như superdog.owner (được tìm nạp riêng)
  • dog.name không giống như superdog.name
  • chó và superdog đều cố gắng viết vào cùng một hàng và sẽ ghi đè lên kết quả của nhau: write3 sẽ hoàn tác thay đổi tên trong write1.

Không có tài liệu tham khảo, bạn có nhiều lần tải hơn, sử dụng nhiều bộ nhớ hơn và giới thiệu khả năng ghi đè các bản cập nhật trước đó.

Giả sử rằng ORM của bạn biết rằng tất cả các tham chiếu đến hàng 1 của bảng chó nên trỏ đến cùng một thứ. Sau đó:

  • fetch4 có thể được loại bỏ vì có một đối tượng trong bộ nhớ tương ứng với Chủ sở hữu.find (1). fetch3 vẫn sẽ dẫn đến ít nhất là quét chỉ mục, vì có thể có những con chó khác thuộc sở hữu của chủ sở hữu, nhưng sẽ không kích hoạt truy xuất hàng.
  • chó và superdog chỉ vào cùng một đối tượng.
  • dog.name và superdog.name trỏ đến cùng một đối tượng.
  • dog.owner và superdog.owner trỏ đến cùng một đối tượng.
  • write3 không ghi đè lên sự thay đổi trong write1.

Nói cách khác, sử dụng tài liệu tham khảo giúp mã hóa nguyên tắc của một điểm duy nhất (ít nhất là trong luồng đó) là hàng trong cơ sở dữ liệu.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.