Ý nghĩa của dấu gạch dưới đơn và kép trước tên đối tượng là gì?


1292

Ai đó có thể vui lòng giải thích ý nghĩa chính xác của việc có dấu gạch dưới hàng đầu trước tên của một đối tượng trong Python và sự khác biệt giữa cả hai không?

Ngoài ra, ý nghĩa đó có giữ nguyên cho dù đối tượng trong câu hỏi là một biến, một hàm, một phương thức, v.v.?


2
Một câu trả lời ngắn tuyệt vời từ một chủ đề khác: stackoverflow.com/a/8689983/911945
Anton Tarasenko

Câu trả lời:


1155

Dấu gạch đơn

Các tên, trong một lớp, với dấu gạch dưới hàng đầu chỉ đơn giản là để chỉ ra cho các lập trình viên khác rằng thuộc tính hoặc phương thức được dự định là riêng tư. Tuy nhiên, không có gì đặc biệt được thực hiện với chính tên của nó.

Để trích dẫn PEP-8 :

_single_lead_underscore: chỉ số "sử dụng nội bộ" yếu. Ví dụ: from M import *không nhập các đối tượng có tên bắt đầu bằng dấu gạch dưới.

Dấu gạch dưới đôi (Tên Mangling)

Từ các tài liệu Python :

Bất kỳ định danh nào của biểu mẫu __spam(ít nhất là hai dấu gạch dưới hàng đầu, nhiều nhất là một dấu gạch dưới) được thay thế bằng văn bản _classname__spam, trong đó classnametên lớp hiện tại có dấu gạch dưới hàng đầu. Việc xáo trộn này được thực hiện mà không liên quan đến vị trí cú pháp của mã định danh, do đó, nó có thể được sử dụng để xác định các thể hiện lớp riêng và các biến lớp, phương thức, biến được lưu trữ trong toàn cục và thậm chí các biến được lưu trữ trong các thể hiện. riêng tư cho lớp này trong các trường hợp của các lớp khác.

Và một cảnh báo từ cùng một trang:

Việc xáo trộn tên được dự định để cung cấp cho các lớp một cách dễ dàng để xác định các biến và phương thức cá thể của riêng tư, mà không phải lo lắng về các biến thể hiện được xác định bởi các lớp dẫn xuất hoặc mucking với các biến thể hiện bằng mã bên ngoài lớp. Lưu ý rằng các quy tắc xáo trộn được thiết kế chủ yếu để tránh tai nạn; linh hồn xác định vẫn có thể truy cập hoặc sửa đổi một biến được coi là riêng tư.

Thí dụ

>>> class MyClass():
...     def __init__(self):
...             self.__superprivate = "Hello"
...             self._semiprivate = ", world!"
...
>>> mc = MyClass()
>>> print mc.__superprivate
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute '__superprivate'
>>> print mc._semiprivate
, world!
>>> print mc.__dict__
{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}

17
Điều gì xảy ra nếu có một tên biến được khai báo với 2 dấu gạch dưới không có trong lớp? Đó chỉ là một biến số bình thường phải không?
Dhruv Ramani

5
ý nghĩa của việc đơn giản __gấp đôi dấu gạch dưới làm tên biến là gì? thícha, __ = foo()
AJ

104
Câu trả lời này cực kỳ sai lệch, vì nó khiến người đọc tin rằng dunderscore được sử dụng để tạo ra các thuộc tính cá thể là "superprivate". Đây không phải là trường hợp, như được giải thích ở đây bởi Raymond Hettinger, người tuyên bố rõ ràng rằng dunderscore được sử dụng một cách bất thường để đánh dấu các thành viên riêng tư, trong khi nó được thiết kế trái ngược với riêng tư.
Markus Meskanen

13
@MarkusMeskanen Tôi không đồng ý, câu trả lời nêu rõ việc sử dụng một dunderscore để tạo ra các thể hiện của các biến và phương thức riêng tư lớp. Trong khi dunderscore được thiết kế để làm cho các phương thức và biến này dễ dàng bị ghi đè bởi các lớp con (làm cho chúng công khai), việc sử dụng một dunderscore giữ một cá thể riêng để sử dụng trong lớp đó.
arewm

6
@MarkusMeskanen: Sự tự do dành cho các lớp con sử dụng cùng tên với siêu lớp mà không bị che khuất siêu lớp - nói cách khác, các tên giả của siêu lớp trở thành riêng tư.
Ethan Furman

311

Câu trả lời tuyệt vời cho đến nay nhưng một số mẩu tin bị thiếu. Một dấu gạch dưới hàng đầu duy nhất không chính xác chỉ là một quy ước: nếu bạn sử dụng from foobar import *và mô-đun foobarkhông xác định __all__danh sách, các tên được nhập từ mô-đun không bao gồm các tên có dấu gạch dưới hàng đầu. Hãy nói rằng đó chủ yếu là một quy ước, vì trường hợp này là một góc khá tối nghĩa ;-).

Quy ước hàng đầu gạch được sử dụng rộng rãi không chỉ cho riêng tên, mà còn cho những gì C ++ sẽ gọi bảo vệ những người - ví dụ, tên của phương pháp được thiết kế đầy đủ để được ghi đè bởi lớp con (ngay cả những cái đó được ghi đè vì trong lớp cơ sở họ raise NotImplementedError! -) thường là các tên đơn hàng đầu-gạch dưới để chỉ ra mã bằng cách sử dụng các thể hiện của lớp đó (hoặc các lớp con) mà các phương thức đã nói không được gọi trực tiếp.

Ví dụ: để tạo một hàng đợi an toàn theo luồng với một kỷ luật xếp hàng khác so với FIFO, một người nhập hàng đợi, lớp con Queue.Queue và ghi đè các phương thức như _get_put; "mã máy khách" không bao giờ gọi các phương thức ("hook") đó, mà là các phương thức công khai ("tổ chức") như putget(đây được gọi là mẫu thiết kế Phương thức mẫu - xem ví dụ ở đây để trình bày thú vị dựa trên video của một bài nói chuyện của tôi về chủ đề này, với việc bổ sung các bản tóm tắt của bảng điểm).

Chỉnh sửa: Các liên kết video trong phần mô tả các cuộc đàm phán hiện đã bị hỏng. Bạn có thể tìm thấy hai video đầu tiên ở đâyở đây .


1
Vậy làm thế nào để bạn quyết định nên sử dụng _var_namehoặc sử dụng var_name+ loại trừ nó khỏi __all__?
endolith

3
@endolith Sử dụng dấu gạch dưới hàng đầu để báo hiệu cho người đọc mã của bạn rằng họ có thể không nên sử dụng mã này (ví dụ: vì bạn có thể thay đổi mã trong phiên bản 2.0 hoặc thậm chí 1.1); sử dụng rõ ràng __all__bất cứ khi nào bạn muốn làm cho mô-đun from spam import *thân thiện (bao gồm cả tại trình thông dịch tương tác). Vì vậy, hầu hết thời gian, câu trả lời là cả hai .
abarnert

@AlexMartelli Quy tắc liên quan đến nhập khẩu này có được thảo luận hợp pháp ở đâu đó trong tài liệu hoặc ở nơi khác không?
Vicrobot

1
Tôi thích sự tương tự C ++. Thứ nhất, tôi không thích nó khi mọi người gọi là _ riêng tư . Rõ ràng là tôi đang nói về sự tương tự, vì không có gì thực sự riêng tư trong Python. Khi đi sâu vào ngữ nghĩa, tôi muốn nói rằng chúng ta có thể liên kết _với Java được bảo vệ vì được đề xuất trong Java có nghĩa là "các lớp dẫn xuất và / hoặc trong cùng một gói". Thay thế gói bằng mô-đun vì PEP8 đã cho chúng tôi biết rằng đó _không chỉ là quy ước khi nói về *nhập khẩu và bạn có nó. Và chắc chắn __sẽ tương đương với riêng tư của Java khi nói về các định danh trong một lớp.
Marius Mucenicu

2
Trong khi một câu trả lời đàng hoàng, nó cũng rất tự quảng cáo.
Lai web dev

298

__foo__: đây chỉ là một quy ước, một cách để hệ thống Python sử dụng các tên không xung đột với tên người dùng.

_foo: đây chỉ là một quy ước, một cách để lập trình viên chỉ ra rằng biến đó là riêng tư (bất cứ điều gì có nghĩa là trong Python).

__foo: điều này có ý nghĩa thực sự: trình thông dịch thay thế tên này _classname__foonhư một cách để đảm bảo rằng tên đó sẽ không trùng với tên tương tự trong một lớp khác.

Không có hình thức gạch dưới nào khác có ý nghĩa trong thế giới Python.

Không có sự khác biệt giữa lớp, biến, toàn cầu, vv trong các quy ước này.


6
Chỉ cần đi qua __foovà tò mò. Làm thế nào nó có thể trùng lặp với các tên phương thức tương tự với các Lớp khác? Ý tôi là bạn vẫn phải truy cập nó như thế nào instance.__foo()(nếu nó không được đổi tên bởi trình thông dịch), phải không?
Bibhas Debnath

81
Anh chàng này tuyên bố rằng from module import *không nhập các đối tượng có tiền tố gạch dưới. Do đó, _fookhông chỉ là một quy ước.
dotancohen

4
@Bibhas: nếu lớp Bcon lớp lớp Avà cả hai thực hiện foo(), sau đó B.foo()ghi đè lên .foo()kế thừa từ A. Một thể hiện của Bsẽ chỉ có thể truy cập B.foo(), ngoại trừ thông qua super(B).foo().
vô hiệu hóa

3
Đối với các __dunder__tên, các yêu cầu ngầm bỏ qua từ điển cá thể, vì vậy có lẽ nó không chỉ là một quy ước đặt tên trong một số trường hợp (xem phần tra cứu phương thức đặc biệt trong datamodel).
Wim

206

._variable là semiprivate và có nghĩa là chỉ dành cho hội nghị

.__variablethường được coi là siêu bí mật, trong khi ý nghĩa thực sự của nó chỉ là đặt tên cho nam để tránh truy cập ngẫu nhiên [1]

.__variable__ thường được dành riêng cho các phương thức dựng sẵn hoặc các biến

Bạn vẫn có thể truy cập .__mangledcác biến nếu bạn rất muốn. Các dấu gạch dưới kép chỉ là tên, hoặc đổi tên, biến thành một cái gì đó nhưinstance._className__mangled

Thí dụ:

class Test(object):
    def __init__(self):
        self.__a = 'a'
        self._b = 'b'

>>> t = Test()
>>> t._b
'b'

t._b có thể truy cập được vì nó chỉ bị ẩn theo quy ước

>>> t.__a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute '__a'

t .__ a không được tìm thấy vì nó không còn tồn tại do đặt tên

>>> t._Test__a
'a'

Bằng cách truy cập instance._className__variablethay vì chỉ tên gạch dưới kép, bạn có thể truy cập giá trị ẩn


nhưng nếu "__a" là một biến lớp thì bạn không thể truy cập nó ngay cả với các hướng dẫn từ tài liệu python ..
Vitaliy Terziev

Xin vui lòng bạn có thể cập nhật câu trả lời của bạn với một ví dụ về dấu gạch dưới kép liên quan đến sự kế thừa?
biến

116

Dấu gạch dưới đơn ở đầu:

Python không có phương thức riêng tư thực sự. Thay vào đó, một dấu gạch dưới khi bắt đầu một phương thức hoặc tên thuộc tính có nghĩa là bạn không nên truy cập phương thức này, vì đó không phải là một phần của API.

class BaseForm(StrAndUnicode):

    def _get_errors(self):
        "Returns an ErrorDict for the data provided for the form"
        if self._errors is None:
            self.full_clean()
        return self._errors

    errors = property(_get_errors)

(Đoạn mã này được lấy từ mã nguồn django: django / Forms / Forms.py). Trong mã này, errorslà một thuộc tính công cộng, nhưng phương thức mà thuộc tính này gọi là _get_errors là "riêng tư", vì vậy bạn không nên truy cập nó.

Hai dấu gạch dưới ở đầu:

Điều này gây ra nhiều nhầm lẫn. Nó không nên được sử dụng để tạo ra một phương thức riêng tư. Nó nên được sử dụng để tránh phương thức của bạn bị ghi đè bởi một lớp con hoặc vô tình truy cập. Hãy xem một ví dụ:

class A(object):
    def __test(self):
        print "I'm a test method in class A"

    def test(self):
        self.__test()

a = A()
a.test()
# a.__test() # This fails with an AttributeError
a._A__test() # Works! We can access the mangled name directly!

Đầu ra:

$ python test.py
I'm test method in class A
I'm test method in class A

Bây giờ hãy tạo một lớp con B và thực hiện tùy chỉnh cho phương thức __test

class B(A):
    def __test(self):
        print "I'm test method in class B"

b = B()
b.test()

Đầu ra sẽ là ....

$ python test.py
I'm test method in class A

Như chúng ta đã thấy, A.test () đã không gọi các phương thức B .__ test () như chúng ta mong đợi. Nhưng trên thực tế, đây là hành vi đúng cho __. Hai phương thức được gọi là __test () được tự động đổi tên (xáo trộn) thành _A__test () và _B__test (), vì vậy chúng không vô tình ghi đè. Khi bạn tạo một phương thức bắt đầu bằng __, điều đó có nghĩa là bạn không muốn bất kỳ ai có thể ghi đè lên nó và bạn chỉ có ý định truy cập nó từ bên trong lớp của chính nó.

Hai dấu gạch dưới ở đầu và cuối:

Khi chúng ta thấy một phương thức như thế __this__, đừng gọi nó. Đây là một phương thức mà python có nghĩa là để gọi, không phải bạn. Hãy xem:

>>> name = "test string"
>>> name.__len__()
11
>>> len(name)
11

>>> number = 10
>>> number.__add__(40)
50
>>> number + 50
60

Luôn có một toán tử hoặc hàm riêng gọi các phương thức ma thuật này. Đôi khi nó chỉ là một cuộc gọi trăn trong các tình huống cụ thể. Ví dụ __init__()được gọi khi đối tượng được tạo sau __new__()được gọi để xây dựng thể hiện ...

Hãy lấy một ví dụ ...

class FalseCalculator(object):

    def __init__(self, number):
        self.number = number

    def __add__(self, number):
        return self.number - number

    def __sub__(self, number):
        return self.number + number

number = FalseCalculator(20)
print number + 10      # 10
print number - 20      # 40

Để biết thêm chi tiết, xem hướng dẫn PEP-8 . Để biết thêm các phương pháp kỳ diệu, xem bản PDF này .


1
Sau khi tự mình chỉnh sửa câu trả lời này, tôi thích stackoverflow.com/a/8689983/1048186
Josiah Yoder

Ý bạn là gì khi "Như chúng ta đã thấy, A.test () không gọi các phương thức B .__ test ()" - bạn đã gọi A.test () ở đâu?
biến

18

Đôi khi bạn có những gì dường như là một tuple với dấu gạch dưới hàng đầu như trong

def foo(bar):
    return _('my_' + bar)

Trong trường hợp này, điều đang xảy ra là _ () là bí danh cho chức năng bản địa hóa hoạt động trên văn bản để đưa nó vào ngôn ngữ phù hợp, v.v. dựa trên ngôn ngữ. Ví dụ: Sphinx thực hiện điều này và bạn sẽ tìm thấy trong số hàng nhập khẩu

from sphinx.locale import l_, _

và trong sphinx.locale, _ () được gán làm bí danh của một số chức năng bản địa hóa.


11

Vì rất nhiều người đang nhắc đến Raymond's cuộc nói chuyện , tôi sẽ làm cho nó dễ dàng hơn một chút bằng cách viết ra những gì anh ấy nói:

Ý định của dấu gạch dưới đôi không phải là về quyền riêng tư. Ý định là sử dụng nó chính xác như thế này

class Circle(object):

    def __init__(self, radius):
        self.radius = radius

    def area(self):
        p = self.__perimeter()
        r = p / math.pi / 2.0
        return math.pi * r ** 2.0

    def perimeter(self):
        return 2.0 * math.pi * self.radius

    __perimeter = perimeter  # local reference


class Tire(Circle):

    def perimeter(self):
        return Circle.perimeter(self) * 1.25

Nó thực sự trái ngược với sự riêng tư, đó là tất cả về tự do. Nó làm cho các lớp con của bạn tự do ghi đè bất kỳ một phương thức nào mà không phá vỡ các phương thức khác .

Nói rằng bạn không giữ một tài liệu tham khảo địa phương perimetertrong Circle. Bây giờ, một lớp dẫn xuất Tireghi đè lên việc thực hiện perimeter, mà không cần chạm vào area. Khi bạn gọi Tire(5).area(), theo lý thuyết, nó vẫn nên được sử dụng Circle.perimeterđể tính toán, nhưng trong thực tế, nó đang sử dụng Tire.perimeter, đó không phải là hành vi dự định. Đó là lý do tại sao chúng ta cần một tài liệu tham khảo địa phương trong Circle.

Nhưng tại sao __perimeterthay vì _perimeter? Bởi vì _perimetervẫn cho lớp dẫn xuất cơ hội ghi đè:

class Tire(Circle):

    def perimeter(self):
        return Circle.perimeter(self) * 1.25

    _perimeter = perimeter

Double undercores có tên xáo trộn, vì vậy rất ít khả năng tham chiếu cục bộ trong lớp cha được ghi đè trong lớp dẫn xuất. do đó " làm cho các lớp con của bạn tự do ghi đè bất kỳ một phương thức nào mà không phá vỡ các phương thức khác ".

Nếu lớp của bạn sẽ không được kế thừa hoặc phương thức ghi đè không phá vỡ bất cứ điều gì, thì đơn giản là bạn không cần __double_leading_underscore.


1
Cảm ơn bạn, slide không hiển thị chính xác nên cuối cùng tôi đã không tiết lộ lý do tại sao mã của tôi sẽ thất bại.
cgte

8

Nếu một người thực sự muốn tạo một biến chỉ đọc, IMHO cách tốt nhất là sử dụng thuộc tính () chỉ với getter được truyền cho nó. Với property () chúng ta có thể kiểm soát hoàn toàn dữ liệu.

class PrivateVarC(object):

    def get_x(self):
        pass

    def set_x(self, val):
        pass

    rwvar = property(get_p, set_p)  

    ronly = property(get_p) 

Tôi hiểu rằng OP đã hỏi một câu hỏi nhỏ khác nhau nhưng vì tôi tìm thấy một câu hỏi khác hỏi 'làm thế nào để đặt các biến riêng tư được đánh dấu trùng lặp với câu hỏi này, tôi đã nghĩ đến việc thêm thông tin bổ sung này vào đây.


8

Tham gia vào https://dbader.org/blog/meaning-of-underscores-in-python

  • Single Underscore (_var) : Quy ước đặt tên cho biết tên có nghĩa là sử dụng nội bộ. Nói chung không được thi hành bởi trình thông dịch Python (ngoại trừ trong nhập ký tự đại diện) và chỉ có ý nghĩa như một gợi ý cho lập trình viên.
  • Dấu gạch ngang đơn (var_) : Được sử dụng theo quy ước để tránh xung đột đặt tên với từ khóa Python.
  • Double Underscore (__ var) : Tên kích hoạt xáo trộn khi được sử dụng trong ngữ cảnh lớp. Được thực thi bởi trình thông dịch Python.
  • Double Under and Trailing Underscore (__ var__) : Biểu thị các phương thức đặc biệt được xác định bởi ngôn ngữ Python. Tránh sơ đồ đặt tên này cho các thuộc tính của riêng bạn.
  • Dấu gạch dưới đơn (_) : Đôi khi được sử dụng làm tên cho các biến tạm thời hoặc không đáng kể (không cần quan tâm). Ngoài ra: Kết quả của biểu thức cuối cùng trong REPL của Python.

5

Câu trả lời tuyệt vời và tất cả đều đúng. Tôi đã cung cấp ví dụ đơn giản cùng với định nghĩa / ý nghĩa đơn giản.

Ý nghĩa:

some_variable - ► nó công khai bất cứ ai cũng có thể thấy điều này.

_some_variable - ► mọi người đều có thể thấy điều này nhưng đó là một quy ước để chỉ ra ... cảnh báo riêng tư không có sự thực thi nào được thực hiện bởi Python.

__some_varaible - ► Python thay thế tên biến bằng _ classname__some_varaible (xáo trộn tên AKA) và nó làm giảm / ẩn khả năng hiển thị của nó và giống như biến riêng tư hơn.

Thành thật mà nói ở đây Theo tài liệu Python

"Các biến đối tượng của Private Private không thể truy cập được ngoại trừ từ bên trong một đối tượng không tồn tại trong Python"

Ví dụ:

class A():
    here="abc"
    _here="_abc"
    __here="__abc"


aObject=A()
print(aObject.here) 
print(aObject._here)
# now if we try to print __here then it will fail because it's not public variable 
#print(aObject.__here)

_ _some_varaible - .... và nó làm giảm / che giấu khả năng hiển thị của nó và giống như biến riêng tư hơn. Không, tên xáo trộn là điểm chính, nó không ẩn phương thức.
AMC

4

Đơn lẻ hàng đầu là một quy ước. không có sự khác biệt từ quan điểm của người phiên dịch nếu tên bắt đầu bằng một dấu gạch dưới hay không.

Dấu gạch dưới hàng đầu và dấu kép được sử dụng cho các phương thức tích hợp, chẳng hạn như __init__,__bool__ vv

Double undererscores w / o trailing đối tác cũng là một quy ước, tuy nhiên, các phương thức lớp sẽ được trình thông dịch đọc sai . Đối với các biến hoặc tên hàm cơ bản không có sự khác biệt tồn tại.


3

Câu hỏi của bạn là tốt, nó không chỉ là về phương pháp. Các hàm và đối tượng trong các mô-đun thường được thêm tiền tố với một dấu gạch dưới và cũng có thể được tiền tố bởi hai.

Nhưng ví dụ, tên __double_underscore không được đặt tên trong các mô-đun. Điều gì xảy ra là tên bắt đầu bằng một (hoặc nhiều) dấu gạch dưới không được nhập nếu bạn nhập tất cả từ một mô-đun (từ nhập mô-đun *), cũng không phải là tên được hiển thị trong trợ giúp (mô-đun).


1
Hơn nữa, các tên bắt đầu bằng một hoặc nhiều dấu gạch dưới có hai hoặc nhiều dấu gạch dưới kéo dài hoạt động như bất kỳ tên nào khác một lần nữa.
Bentley4

3

Dưới đây là một ví dụ minh họa đơn giản về cách các thuộc tính gạch dưới có thể ảnh hưởng đến một lớp kế thừa. Vì vậy, với các thiết lập sau:

class parent(object):
    __default = "parent"
    def __init__(self, name=None):
        self.default = name or self.__default

    @property
    def default(self):
        return self.__default

    @default.setter
    def default(self, value):
        self.__default = value


class child(parent):
    __default = "child"

Nếu sau đó bạn tạo một cá thể con trong REPL python, bạn sẽ thấy bên dưới

child_a = child()
child_a.default            # 'parent'
child_a._child__default    # 'child'
child_a._parent__default   # 'parent'

child_b = child("orphan")
## this will show 
child_b.default            # 'orphan'
child_a._child__default    # 'child'
child_a._parent__default   # 'orphan'

Điều này có thể rõ ràng với một số người, nhưng nó khiến tôi mất cảnh giác trong một môi trường phức tạp hơn nhiều


3

Các biến đối tượng của riêng tư mà không thể truy cập được, ngoại trừ từ bên trong một đối tượng không tồn tại trong Python. Tuy nhiên, có một quy ước được tuân theo bởi hầu hết mã Python: tên có tiền tố gạch dưới (ví dụ _spam) phải được coi là một phần không công khai của API (cho dù đó là hàm, phương thức hay thành viên dữ liệu) . Nó nên được coi là một chi tiết thực hiện và có thể thay đổi mà không cần thông báo trước.

tham khảo https://docs.python.org/2/tutorial/groupes.html#private-variables-and- class-local-report


1
_ tương tự nhiều hơn với ví dụ nội bộ trong c # sau đó là riêng tư. Double gạch dưới nó giống với tư nhân hơn thì gạch dưới là riêng tư tôi sẽ nói.
Ini

2

Lấy thông tin về _ và __ khá dễ dàng; các câu trả lời khác thể hiện chúng khá tốt. Việc sử dụng là khó khăn hơn nhiều để xác định.

Đây là cách tôi nhìn thấy nó:

_

Nên được sử dụng để chỉ ra rằng một chức năng không dành cho sử dụng công cộng, ví dụ như API. Điều này và hạn chế nhập khẩu làm cho nó hoạt động giống như internaltrong c #.

__

Nên được sử dụng để tránh xung đột tên trong chế độ thừa kế thừa kế và để tránh bị trễ. Giống như tư nhân trong c #.

==>

Nếu bạn muốn chỉ ra rằng một cái gì đó không dành cho sử dụng công cộng, nhưng nó nên hoạt động như protectedsử dụng _. Nếu bạn muốn chỉ ra rằng một cái gì đó không dành cho công chúng, nhưng nó nên hoạt động như privatesử dụng__ .

Đây cũng là một trích dẫn mà tôi rất thích:

Vấn đề là tác giả của một lớp có thể nghĩ rằng "tên thuộc tính / phương thức này phải là riêng tư, chỉ có thể truy cập từ trong định nghĩa lớp này" và sử dụng quy ước __private. Nhưng sau này, một người dùng của lớp đó có thể tạo một lớp con cần truy cập hợp pháp vào tên đó. Vì vậy, hoặc siêu lớp phải được sửa đổi (có thể khó hoặc không thể) hoặc mã lớp con phải sử dụng tên xéo thủ công (tốt nhất là xấu và dễ vỡ).

Nhưng vấn đề với tôi là nếu không có IDE nào cảnh báo bạn khi bạn ghi đè các phương thức, việc tìm lỗi có thể khiến bạn mất một thời gian nếu bạn vô tình ghi đè một phương thức từ lớp cơ sở.

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.