• Vui lòng đọc nội qui diễn đàn để tránh bị xóa bài viết
  • Tìm kiếm trước khi đặt câu hỏi

Toán tử so sánh trong OOP.

Nơi trao đổi, hỏi đáp về hướng đối tượng (OOP - Object-Oriented Programming), không giới hạn về ngôn ngữ lập trình
Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 87 time
Liên hệ:

Toán tử so sánh trong OOP.

Gửi bàigửi bởi vo_minhdat2007 » T.Tư 31/08/2011 5:50 pm

Tên bài viết: Toán tử = và <> (== và != hoặc ~=) trong OOP.
Tác giả: vo_minhdat2007
Cấp độ bài viết: Sơ cấp
Tóm tắt: Thảo luận về toán tử so sánh "giống" và "khác" giữa 2 object trong OOP.


Đối với bài viết hướng dẫn đầu tiên cho box OOP, mình xin trình bày một vấn đề vô cùng cơ bản nhưng rất hay gặp với người mới, đó là việc "so sánh" 2 object. Trước tiên, về quy ước trong bài viết này, dấu = để so sánh "bằng" (tương ứng toán tử = trong VB, == trong Java/C#/LUA) và dấu <> để so sánh "khác" (tương ứng toán tử <> trong VB, != trong Java/C#, ~= trong LUA).

1. Tác dụng của toán tử = và <>:

Toán tử =<> là toán tử Boolean, trả về 2 giá trị là true và false. Đối với OOP, toán tử = trả về giá trị true nếu 2 hạng tử cùng trỏ đến 1 đối tượng, ngược lại thì toán tử <> sẽ trả về giá trị true.

Ví dụ:
  1. Foo a = new Foo(); Foo b = a; Foo c = a; Foo d = new Foo(); a = null;


Đoạn code trên tương đương đoạn dưới đây trong VB.NET:

  1. Dim a As New Foo() : Dim b As Foo = a : Dim c as Foo = a : Dim d as New Foo() : a = Nothing


Và đây là bảng kết quả khi so sánh bằng toán tử =:

result.png
result.png (2.13 KiB) Đã xem 8154 lần


Ở đây, việc so sánh cùng 1 biến lúc nào cũng trả về True (kể cả Nothing = Nothing). Chúng ta có thể phân tích lí do kết quả trên:
  • Foo a = new Foo(); Tạo một đối tượng kiểu Foo tại ô nhớ X, trỏ biến a kiểu Foo đến ô nhớ này.
  • Foo b = a; Trỏ biến b kiểu Foo đến ô nhớ mà biến a đang trỏ, tức ô nhớ X.
  • Foo c = a; Trỏ biến c kiểu Foo đến ô nhớ mà biến a đang trỏ, tức ô nhớ X.
  • Foo d = new Foo(); Tạo một đối tượng kiểu Foo tại ô nhớ Y, trỏ biến d kiểu Foo đến ô nhớ này.
  • a = null; Biến a bây giờ không trỏ đến ô nhớ nào nữa.
Tóm lại, sau quá trình trên, biến a sẽ không trỏ đến ô nhớ nào, tức Nothing; biến b và c cùng trỏ đến ô nhớ X và biến d trỏ đến ô nhớ Y. Do vậy, chỉ có b = c là True (do 2 biến cùng trỏ đến ô nhớ X). Mặc dù cả ô X và Y đều có giá trị giống nhau (do đều chỉ gọi New Foo()), nhưng b <> d, do không cùng trỏ vào một ô nhớ.

2. Một số sai sót hay mắc phải của người mới:

Điều đáng lưu ý trước tiên mà chính mình cũng từng gặp là kiểu String của Java. String không phải là một primitive type, mà là một kiểu object đặc biệt. Do vậy, toán tử == không so sánh giá trị String đó mà là ô nhớ. Ví dụ:

  1. String a = "Câu lạc bộ Visual Basic";
  2. String b = "Câu lạc bộ Visual Basic";
  3.  
  4. return a == b; // Trả về false, do a và b trỏ đến 2 ô nhớ hoàn toàn khác nhau.
  5. return a.equals(b); // Lỗi deadcode, nếu xoá dòng return ở trên sẽ trả về true.


String của .NET được xử lí để tránh sai lầm trên, nhưng các bạn cũng nên làm quen với phương thức equals, dùng để so sánh giá trị của 2 object (chứ không phải vị trí ô nhớ).

Một vấn đề khác là các bạn lập trình cấu trúc chuyển qua thường xuyên quên khởi tạo đối tượng:

Với đoạn code trên, chắc chắn bạn sẽ nhận ngay NullPointerException. Do ở dòng trên, bạn mới khai báo a kiểu Foo, chứ chưa hề khởi tạo đối tượng thực sự nào trong bộ nhớ. Vì vậy bạn phải dùng:
  1. Dim a As New Foo()
  2. a.DoSomething()


Cũng một vấn đề khá thú vị khi vừa chuyển sang OOP từ hướng cấu trúc:
  1. Foo a = new Foo();
  2. a.myValue = 5;
  3. Foo b = a;
  4. b.myValue = 10;


Lúc này, nhiều bạn cứ nghĩ b.myValue là 10 (đúng), và a.myValue là 5 (sai). Tại sao vậy? a.myValue là 10. Chỉ cần liệt kê các bước là chúng ta hiểu ngay:
  • Foo a = new Foo(); Khởi tạo đối tượng kiểu Foo tại ô nhớ X, biến a kiểu Foo trỏ vào ô nhớ này.
  • a.myValue = 5; Gán giá trị 5 cho myValue của đối tượng tại ô nhớ X.
  • Foo b = a;Không khởi tạo đối tượng mới, biến b kiểu Foo trỏ vào ô nhớ X (là ô nhớ mà a đang trỏ đến).
  • b.myValue = 10;Gán giá trị 10 cho myValue của đối tượng tại ô nhớ X.
Như vậy, rõ ràng tuy là 2 biến khác nhau, nhưng cả 2 cùng trỏ vào cùng một ô nhớ, nên hễ thay đổi giá trị b thì a cũng sẽ thay đổi theo và ngược lại. Các bạn nên cẩn thận khi làm việc với OOP.

Bài viết đầu tiên về OOP của mình nên cũng sẽ không tránh khỏi sai sót, nhất là do mức độ chặt chẽ của nó, vì vậy mong các bạn cùng tham gia góp ý, cũng như thảo luận những điều hay về 2 toán tử so sánh này.

Thân.



Hình đại diện của người dùng
Dang Minh Du
Thành viên ưu tú
Thành viên ưu tú
Bài viết: 531
Ngày tham gia: T.Tư 02/04/2008 2:08 pm
Đến từ: RGames Team
Has thanked: 3 time
Been thanked: 17 time
Liên hệ:

Re: Toán tử so sánh trong OOP.

Gửi bàigửi bởi Dang Minh Du » T.Năm 01/09/2011 8:28 am

Thanks về vấn đề cuối! Trước giờ k làm phép gán như vậy cũng như chưa dc ai nhắc nhỡ lưu ý nên a k hề biết chuyện này ;))

Hình đại diện của người dùng
alexanderdna
Guru
Guru
Bài viết: 214
Ngày tham gia: T.Ba 14/07/2009 11:13 am
Đến từ: Sài Gòn
Has thanked: 3 time
Been thanked: 15 time

Re: Toán tử so sánh trong OOP.

Gửi bàigửi bởi alexanderdna » T.Năm 01/09/2011 12:17 pm

Cũng cần lưu ý thêm một số vấn đề sau đây.

Thứ nhất là, trong một số ngôn ngữ OOP như C#, toán tử có thể được định nghĩa khác đi. Lúc này, toán tử == và != có thể không còn là so sánh tham chiếu nữa. Bên cạnh đó, cũng trong C# và các ngôn ngữ OOP khác của .NET, có loại kiểu dữ liệu là Value Type (kiểu trị). Toán tử == và != trên kiểu dữ liệu này cũng không phải so sánh tham chiếu.

Thứ nhì là, trên C++, một ngôn ngữ OOP phổ biến, dữ liệu mặc định là kiểu trị chứ không phải kiểu tham chiếu. Do đó, phép gán đã nêu không gây lỗi tham chiếu. Lỗi này chỉ xảy ra nếu gán con trỏ, khi toán tử gán (=) chưa được định nghĩa lại.

Hình đại diện của người dùng
vo_minhdat2007
Quản trị
Quản trị
Bài viết: 2227
Ngày tham gia: CN 17/07/2005 1:40 am
Has thanked: 13 time
Been thanked: 87 time
Liên hệ:

Re: Toán tử so sánh trong OOP.

Gửi bàigửi bởi vo_minhdat2007 » T.Năm 01/09/2011 12:25 pm

À, mình quên nhấn mạnh chỗ này, ở Tóm tắt mình có ghi, nhưng có lẽ chưa nổi bật:

Thảo luận về toán tử so sánh "giống" và "khác" giữa 2 object trong OOP.


Cảm ơn bạn đã góp ý,
Thân.

Hình đại diện của người dùng
alexanderdna
Guru
Guru
Bài viết: 214
Ngày tham gia: T.Ba 14/07/2009 11:13 am
Đến từ: Sài Gòn
Has thanked: 3 time
Been thanked: 15 time

Re: Toán tử so sánh trong OOP.

Gửi bàigửi bởi alexanderdna » T.Năm 01/09/2011 8:42 pm

Mình đoán bạn ngầm định object là thực thể kiểu tham chiếu.

Nói một cách chính xác thì object là bất cứ thực thể nào tạo nên từ một kiểu dữ liệu đã định nghĩa. Theo đó, không có sự phân biệt giữa thực thể của kiểu tham chiếu và thực thể của kiểu trị. Và thực chất, sự phân biệt kiểu tham chiếu và kiểu trị cũng chỉ mang tính chất ngôn ngữ, không lệ thuộc vào OOP. Một số ngôn ngữ OOP chỉ cung cấp kiểu tham chiếu, một số khác chỉ có kiểu trị. Mọi thực thể trong đó đều gọi là object.

Promane
Thành viên chính thức
Thành viên chính thức
Bài viết: 21
Ngày tham gia: T.Hai 13/02/2012 7:59 pm
Has thanked: 5 time

Re: Toán tử so sánh trong OOP.

Gửi bàigửi bởi Promane » T.Năm 05/04/2012 7:54 pm

Mình là amater 100%, theo như bài của bạn thì khi mình sử dụng toán tử (=) trong ví dụ cuối của bạn, thì có nghĩa là a.MyValue = b.MyValue = 10 cho cùng trỏ tới một ô nhớ X, vậy nếu mình muốn gán toàn bộ các giá trị trong a sang b thì làm thế nào ?

solverpvd
Thành viên chính thức
Thành viên chính thức
Bài viết: 40
Ngày tham gia: T.Tư 14/04/2010 11:34 pm
Đến từ: (Phố cổ) Hội An - Quảng Nam
Liên hệ:

Re: Toán tử so sánh trong OOP.

Gửi bàigửi bởi solverpvd » T.Năm 20/06/2013 2:34 pm

Gửi anh vo_minhdat2007
Cho e hỏi toán tử "<<" hay ">>" trong VB.Net là gì ạ. Em tìm tlieu nhưng không thấy.
Em cảm ơn.
PVD

solverpvd
Thành viên chính thức
Thành viên chính thức
Bài viết: 40
Ngày tham gia: T.Tư 14/04/2010 11:34 pm
Đến từ: (Phố cổ) Hội An - Quảng Nam
Liên hệ:

Re: Toán tử so sánh trong OOP.

Gửi bàigửi bởi solverpvd » T.Năm 20/06/2013 4:19 pm

Mình đã tìm ra "lời giải" cho toán tử "<<" hay ">>":
http://www.codeproject.com/Articles/544 ... vTab5VBNET
từ khóa: Understand how bitwise operators work (C# and VB.NET examples)


Quay về “Lập trình hướng đối tượng (OOP)”

Đang trực tuyến

Đang xem chuyên mục này: Không có thành viên nào trực tuyến.1 khách