01/10/2018, 14:49

Tại sao phải có cả biến private và biến public cùng xuất hiện trong khi chỉ 1 là đủ

Code 1:

class Mega
{
    public int A;
}

Code 2:

class A
{
    private int a;
    public int A
    {
        get {return this.a;}
        set {this.a = value;}
    }
}

Cho em hỏi code 1 và 2 cái biến A đó đều cho 1 quá trình sử dụng như nhau (là em thấy vậy).
Vậy tại sao người ta lại xài cái 2 làm gì cho mệt?

Văn Dương viết 16:57 ngày 01/10/2018

Cái này là C#. A lớn gọi là Property. Nếu bạn xét như ví dụ trên sẽ thấy thừa. Nhưng xét thêm thế này.
Bạn sẽ thấy khác biệt lớn nhất là quyền truy cập.

private int a=0;

// lúc này bạn sẽ thấy A chỉ được phép lấy giá trị a mà không được phép gán giá trị cho a.
public int A{
    get{return a;}
}

// lúc này thì vẫn gán được giá trị cho a qua A nhưng chỉ gán được từ bên trong class.
public int A{
    get{return a;}
    private set{a=value;}
}

// hay chỉ gán được từ trong class hoặc từ class kế thừa
public int A{
    get{return a;}
    protected set{a=value;}
}

// hoặc sẽ ném ra một sự kiện mỗi khi a thay đổi. Hoặc để auto update khi binding với WPF
public int A{
    get{return a;}
    set{a=value; NotifyPropertyChanged(...);}
}

// ......
}

Mục đích chính là không cho người viết code khác làm những việc mà người ta không mong muốn khi làm với a. Hạn chế rủi ro khi người khác lỡ tay can thiệp vào a không đúng cách.

Và còn rất nhiều công dụng khác mà khi khai báo một biến public rất khó thực hiện hoặc sẽ phải viết rất nhiều code để thực hiện yêu cầu.

Văn Dương viết 16:52 ngày 01/10/2018

Bạn có thể thử thêm các từ private, protected vào trước get, set hoặc bỏ get hoặc set bạn sẽ thấy nó khác với 1 biến public như thế nào.

Trần Linh viết 16:51 ngày 01/10/2018

E cảm ơn bác :)), em toàn code 1 mình nên ko bit
E chắc sắp trở thành fan của bác rồi :))

HelloWorld viết 16:50 ngày 01/10/2018

2 tính chất đặc trưng của lập trình hướng đối tượng là tính che dấu và tính sử dụng lại
Bạn tham khảo các bài học về class ấy. Sẽ hiểu tại sao có public, private, protected, getter setter, class friend, function friend, method friend…

Trần Linh viết 17:00 ngày 01/10/2018

thực chất là em có học qua nhưng vì code 1 mình nên em đã nghĩ nó ko cần thiết

HelloWorld viết 17:05 ngày 01/10/2018

sao lại code 1 mình là sao nhỉ, mình không hiểu sự liên quan là gì :3

Tao Không Ngu. viết 16:52 ngày 01/10/2018

Hi Trần Linh.
Cái này là tính đóng gói trong OOP nhưng trong C# người ta tối giản đi nhưng vẫn đảm bảo khả năng mở rộng.
VD

class Mega
{
    public int A;
}

Khi cần đổi A thành kiểu float thì phải sửa lại code đã viết nhiều chỗ. Thay vào

class Mega
{
    public int A { get; set; }
}

Thì vẫn dùng như public mà khi cần thay đổi kiểu của biến A thì chỉ viết lại code cho lớp Mega

class Mega
{
    public int A { 
       get => (int) Af; 
       set => Af = value;
    }
   public float Af { get; set;}
}

P/S Nếu chỉ get set không thì bạn có thể viết luôn public int A { get; set; } cho ngắn gọn. Bạn nên kiếm sách đọc để hiểu rõ hơn.

Văn Dương viết 17:01 ngày 01/10/2018

Chắc là bạn ấy làm việc một mình hoặc một mình code cả project.
Tính bao đóng thực sự hiệu quả khi làm trong một team cần chia sẻ code với nhau. Bạn ấy quản lý toàn bộ nên chức năng của tính bao đóng nó mờ nhạt đi.

Property của C# nó thể hiện tính bao đóng như những ngôn ngữ OOP khác. Ngoài ra nó có những chức năng bên lề sẽ thể hiện rất hiệu quả khi dùng với WindowsForm (dùng với DataGridView, ListView, ListBox…) hoặc WPF(databinding) hoặc ASP (tạo json từ đối tượng). Nó rút ngắn đáng kể lượng code và tốc độ thực thi.

HelloWorld viết 17:00 ngày 01/10/2018

Theo em biết 1 chương trình được thiết kế theo oop chính là các đối tượng tương tác với nhau. Mỗi đối tượng được trừu tượng và đóng gói vào class. Vậy 1 chương trình có nhiều class, khi muốn cho các class giao tiếp với nhau sẽ sử dụng đến các khái niệm getter, setter, public, private, protected, friend…nên có thể thấy được tính chất bao đóng ngay. Trừ khi bạn ấy code tất cả vào 1 class. Em chỉ thấy kế thừa và đa hình it dùng hơn nếu bài toán không có đặc điểm đó hoặc người thiết kế lập trình không nhìn ra

Văn Dương viết 16:51 ngày 01/10/2018

Đúng là các object trong một chương trình viết theo kiểu OOP sẽ giao tiếp với nhau. Nhưng nếu bạn để ý sẽ thấy chúng giao tiếp với nhau chính qua các delegate hoặc event (C#) hoặc các hàm callback trong C/C++.

Trần Linh viết 16:59 ngày 01/10/2018

Cái cần ns thì anh @Duong_Act chắc đã ns cho em rồi, ns thật thì cho đến bây giờ em mới thực sự biết mấy cái chức năng mà private, public,… nhưng bây giờ em vẫn chưa đủ kinh nghiệm hoặc chưa được tiếp xúc vs môi trường mà mấy cái này trở nên cần thiết. Vs lại nếu code 1 mình, em ko muốn set biến nào, muốn set biến nào thì quá dễ mà :)).

HelloWorld viết 16:59 ngày 01/10/2018

Theo mình việc giao tiếp giữa các class ở tầng dưới như thế nào thì không rõ, mình cũng đang là sinh viên, chỉ có kiến thức nền, kiến thức cơ bản
Nhưng khi bạn code 1 module, chương trình nếu có nhiều class (2 trở lên) thì bạn sẽ phải động đến các khái niệm getter, settet, public, private, protected, friend…vì các khái niệm này nói về tính đóng gói, vì đóng gói nên giao tiếp giữa các class cũng phải tuân theo 1 số quy tắc trên (dữ liệu nào thì phương thức đó)

Hoặc bạn học môn phân tích thiết kế hướng đối tượng với uml rồi thì sẽ rõ hơn
Nếu đơn giản bạn để tất cả các class là public thì nó không còn đúng theo tính chất hướng đối tượng nữa. Khi đó sẽ có các thành phần phải là private, nhưng private thì lại không thể sử dụng được từ class bên ngoài nên sinh ra các khái niệm getter, setter, friend hoặc protected… Nên theo mình code 1 mình không ảnh hưởng gì đến việc bạn có tiếp xúc nhiều với tính đóng gói hay không

Mình cũng đang xây dựng 1 thư viện, mình code 1 mình và sử dụng rất nhiều các khái niệm trên. Mình cũng chỉ mới xây dựng được mấy class thôi

Hung viết 16:50 ngày 01/10/2018

Klq, khoe thành tích kìa

Văn Dương viết 16:54 ngày 01/10/2018

Xử lý ảnh

HelloWorld viết 17:01 ngày 01/10/2018

Oài , sinh viên quèn, có thành tích gì đâu mà khoe toán mấy bài xử lý trên ma trận để rèn luyện kĩ năng cơ bản thôi mà ~~

Tiến Nguyễn viết 17:02 ngày 01/10/2018

Để tăng tính bảo mật. Đơn giản vậy thôi.

public int A {get;set;}

Thì ở bất kỳ đâu điều có thể truy cập

Còn viết theo cách 2 ý. thì trong phần get;set; có thể thêm bộ lọc vào. kiểu chỉ set số chẵn. get thì phài có điều kiện nào đấy mới get ra được.

public int A
{
get {return this.a;}
set {this.a = value;}
}

Tiến Nguyễn viết 16:53 ngày 01/10/2018

thực chất là em có học qua nhưng vì code 1 mình nên em đã nghĩ nó ko cần thiết

Phải cần thiết thì người ta mới viết vậy.? Đừng suy nghĩ cá nhân vậy chứ.

Trần Linh viết 17:03 ngày 01/10/2018

em kiến thức còn nông cạn

cdxf viết 16:55 ngày 01/10/2018

Thật ra có 2 lý do chính vì sao dùng property mà không dùng field không thấy ai nhắc đến nhỉ.

  1. Reflection, Có rất nhiều thư viện dựa trên reflection mà chỉ hoạt động được trên property.
  2. Binary compatibility
    Giả sử app A dựa trên lib B.
    Lúc này trong lib B có 1 class có 1 field F nào đó mà A dùng. Vậy trong trường hợp anh B này đổi cái field F này thành property (ví dụ thêm validation vào) thì sao: Lúc này app A sẽ không dùng cái lib mới đc vì không tìm thấy trong cái lib B cái field F đâu cả, muốn dùng phải compile lại cái app A.
    Còn nếu dùng property ngay từ đầu thì sao: lib B này chỉ thay đổi implement rồi compile lại nó thôi, app A vẫn dùng lại đc lib B mà không phải compile lại.
    Hay nói đơn giản, nếu app của bạn dựa trên 1 library nào đó, nếu dùng property thì khi library đó ra ver mới bạn chỉ việc ghi đè vào cái library cũ, còn nếu dùng field mà chuyển sang property thì bạn phải compile lại nguyên cái app của bạn.
    Giả sử HĐH có 1 cái lib đc rất nhiều app dùng chung bỗng nhiên đc update lên version mới, trong đó có 1 field đc chuyển thành property thì sau: Lúc này nguyên cái đóng app đó sẽ không chạy đc nữa.

Nguyên tắc cho hầu hết trường hợp: private field, public property.

Bài liên quan
0