Tại sao các ngôn ngữ được quản lý bộ nhớ như Java, Javascript và C # vẫn giữ từ khóa `new`?


139

Các newtừ khóa trong các ngôn ngữ như Java, Javascript, và C # tạo ra một thể hiện mới của một lớp.

Cú pháp này dường như đã được kế thừa từ C ++, nơi newđược sử dụng cụ thể để phân bổ một thể hiện mới của một lớp trên heap và trả về một con trỏ cho thể hiện mới. Trong C ++, đây không phải là cách duy nhất để xây dựng một đối tượng. Bạn cũng có thể xây dựng một đối tượng trên ngăn xếp mà không cần sử dụng new- và trên thực tế, cách xây dựng các đối tượng này phổ biến hơn nhiều trong C ++.

Vì vậy, đến từ nền tảng C ++, newtừ khóa trong các ngôn ngữ như Java, Javascript và C # có vẻ tự nhiên và rõ ràng đối với tôi. Sau đó, tôi bắt đầu học Python, vốn không có newtừ khóa. Trong Python, một cá thể được xây dựng đơn giản bằng cách gọi hàm tạo, như:

f = Foo()

Lúc đầu, điều này có vẻ hơi khó chịu với tôi, cho đến khi tôi nhận ra rằng không có lý do gì để Python có new, bởi vì mọi thứ đều là một đối tượng nên không cần phải phân biệt giữa các cú pháp của hàm tạo khác nhau.

Nhưng sau đó tôi nghĩ - ý nghĩa thực sự của newJava là gì? Tại sao chúng ta nên nói Object o = new Object();? Tại sao không chỉ Object o = Object();? Trong C ++ chắc chắn cần phải có new, vì chúng ta cần phân biệt giữa phân bổ trên heap và phân bổ trên stack, nhưng trong Java tất cả các đối tượng được xây dựng trên heap, vậy tại sao thậm chí còn có newtừ khóa? Câu hỏi tương tự có thể được yêu cầu cho Javascript. Trong C #, điều mà tôi ít quen thuộc hơn, tôi nghĩ newcó thể có một số mục đích trong việc phân biệt giữa các loại đối tượng và loại giá trị, nhưng tôi không chắc chắn.

Bất kể, đối với tôi, dường như nhiều ngôn ngữ xuất hiện sau C ++ chỉ đơn giản là "kế thừa" newtừ khóa - mà không thực sự cần nó. Nó gần giống như một từ khóa di tích . Chúng tôi dường như không cần nó vì bất kỳ lý do gì, nhưng nó vẫn ở đó.

Câu hỏi: Tôi có đúng về điều này không? Hoặc có một số lý do thuyết phục newcần phải có trong C ++ - các ngôn ngữ được quản lý bộ nhớ lấy cảm hứng như Java, Javascript và C # nhưng không phải là Python?


13
Câu hỏi là tại sao bất kỳ ngôn ngữ có newtừ khóa. Tất nhiên tôi muốn tạo một biến mới, trình biên dịch ngu ngốc! Một tốt ngôn ngữ sẽ theo ý kiến của tôi có một cú pháp như f = heap Foo(), f = auto Foo().

7
Một điểm rất quan trọng để xem xét là một ngôn ngữ quen thuộc như thế nào đối với các lập trình viên mới. Java được thiết kế rõ ràng để trông quen thuộc với các lập trình viên C / C ++.

1
@Lundin: Đó thực sự là kết quả của công nghệ biên dịch. Một trình biên dịch hiện đại thậm chí sẽ không cần gợi ý; nó sẽ tìm ra nơi để đặt đối tượng dựa trên việc sử dụng biến đó thực tế của bạn. Tức là khi fkhông thoát khỏi chức năng, phân bổ không gian ngăn xếp.
MSalters

3
@Lundin: Nó có thể, và trên thực tế, các JVM hiện đại làm được. Đây chỉ là vấn đề chứng minh rằng GC có thể thu thập đối tượng fkhi hàm kèm theo trả về.
MSalters

1
Sẽ không mang tính xây dựng để hỏi tại sao một ngôn ngữ được thiết kế theo cách của nó, đặc biệt nếu thiết kế đó yêu cầu chúng ta nhập bốn ký tự phụ để không có lợi ích rõ ràng? Tôi đang thiếu gì?
MatrixFrog

Câu trả lời:


94

Quan sát của bạn là chính xác. C ++ là một con thú phức tạp và newtừ khóa được sử dụng để phân biệt giữa thứ cần thiết deletesau này và thứ gì đó sẽ được tự động lấy lại. Trong Java và C #, họ đã bỏ deletetừ khóa vì trình thu gom rác sẽ chăm sóc nó cho bạn.

Vấn đề là tại sao họ giữ newtừ khóa? Không nói chuyện với những người viết ngôn ngữ, thật khó để trả lời. Dự đoán tốt nhất của tôi được liệt kê dưới đây:

  • Nó đúng về mặt ngữ nghĩa . Nếu bạn đã quen thuộc với C ++, bạn sẽ biết rằng newtừ khóa tạo một đối tượng trên heap. Vì vậy, tại sao thay đổi hành vi dự kiến?
  • Nó gọi sự chú ý đến thực tế là bạn đang khởi tạo một đối tượng chứ không phải gọi một phương thức. Với các đề xuất kiểu mã của Microsoft, tên phương thức bắt đầu bằng chữ in hoa nên có thể gây nhầm lẫn.

Ruby nằm ở đâu đó giữa Python và Java / C # khi sử dụng new. Về cơ bản, bạn khởi tạo một đối tượng như thế này:

f = Foo.new()

Nó không phải là một từ khóa, nó là một phương thức tĩnh cho lớp. Điều đó có nghĩa là nếu bạn muốn có một singleton, bạn có thể ghi đè cài đặt mặc định new()để trả về cùng một thể hiện mỗi lần. Nó không nhất thiết được khuyến khích, nhưng nó có thể.


5
Cú pháp Ruby trông đẹp và nhất quán! Các mới từ khóa trong C # cũng được sử dụng như một loại hạn chế chung cho một loại với một constructor mặc định.
Steven Jeuris

3
Đúng. Chúng tôi sẽ không nói về thuốc generic. Cả hai phiên bản chung của Java và C # đều rất khó hiểu. Không nói C ++ là dễ hiểu hơn nhiều mặc dù. Generics thực sự chỉ hữu ích cho các ngôn ngữ gõ tĩnh. Các ngôn ngữ được gõ động như Python, Ruby và Smalltalk không cần chúng.
Berin Loritsch

2
Delphi có một cú pháp tương tự như Ruby, ngoại trừ các hàm tạo thường (nhưng chỉ là quy ước bhy) được gọi là Tạo (`f: = TFoo.Create (param1, param2 ...) '
Gerry

Trong Objective-C, allocphương thức (gần giống với Ruby new) cũng chỉ là một phương thức lớp.
mipadi

3
Từ quan điểm thiết kế ngôn ngữ, từ khóa là xấu vì nhiều lý do, chủ yếu là bạn không thể thay đổi chúng. Mặt khác, việc sử dụng lại khái niệm phương pháp dễ dàng hơn, nhưng cần một số chú ý trong khi phân tích và phân tích. Smalltalk và người thân của nó sử dụng tin nhắn, C ++ và Itskin trên các từ khóa khác
Gabriel čerbák

86

Tóm lại, bạn đúng. Từ khóa mới là không cần thiết trong các ngôn ngữ như Java và C #. Dưới đây là một số hiểu biết từ Bruce Eckel, một thành viên của C ++ Standard Comitee vào những năm 1990 và sau đó đã xuất bản sách trên Java: http://www.artima.com/weblogs/viewpost.jsp?thread=260578

cần có một số cách để phân biệt các đối tượng heap với các đối tượng stack. Để giải quyết vấn đề này, từ khóa mới đã được chiếm đoạt từ Smalltalk. Để tạo một đối tượng ngăn xếp, bạn chỉ cần khai báo nó, như trong Cat x; hoặc, với các đối số, Cat x ("găng");. Để tạo một đối tượng heap, bạn sử dụng new, như trong Cat mới; hoặc Cat mới ("găng");. Đưa ra các hạn chế, đây là một giải pháp thanh lịch và nhất quán.

Nhập Java, sau khi quyết định rằng mọi thứ C ++ đều được thực hiện kém và quá phức tạp. Điều trớ trêu ở đây là Java có thể và đã đưa ra quyết định vứt bỏ phân bổ ngăn xếp (rõ ràng bỏ qua sự thất bại của các nguyên thủy, mà tôi đã giải quyết ở nơi khác). Và vì tất cả các đối tượng được phân bổ trên heap, nên không cần phân biệt giữa stack và heap phân bổ. Họ có thể dễ dàng nói Cat x = Cat () hoặc Cat x = Cat ("găng"). Hoặc thậm chí tốt hơn, suy luận kiểu kết hợp để loại bỏ sự lặp lại (nhưng điều đó - và các tính năng khác như đóng cửa - sẽ mất "quá lâu" nên chúng tôi bị mắc kẹt với phiên bản Java tầm thường thay vào đó, suy luận kiểu đã được thảo luận nhưng tôi sẽ thảo luận tỷ lệ cược sẽ không xảy ra. Và không nên, đưa ra các vấn đề trong việc thêm các tính năng mới vào Java).


2
Stack vs Heap ... sâu sắc, sẽ không bao giờ nghĩ về nó.
WernerCD

1
"loại suy luận đã được thảo luận nhưng tôi sẽ đặt ra tỷ lệ cược sẽ không xảy ra.", :) Vâng, sự phát triển của Java vẫn còn tiếp tục. Điều thú vị là đây là flagship duy nhất cho Java 10. Các vartừ khóa là hư không gần tốt như autotrong C ++, nhưng tôi hy vọng nó sẽ được cải thiện.
patrik

15

Có hai lý do tôi có thể nghĩ ra:

  • new phân biệt giữa một đối tượng và nguyên thủy
  • Các newcú pháp là dễ đọc hơn một chút (IMO)

Thứ nhất là tầm thường. Tôi không nghĩ rằng khó khăn hơn để phân biệt hai bên. Thứ hai là một ví dụ về quan điểm của OP, đó newlà loại dư thừa.

Có thể có xung đột không gian tên, mặc dù; xem xét:

public class Foo {
   Foo() {
      // Constructor
   }
}

public class Bar {
   public static void main(String[] args) {
      Foo f = Foo();
   }

   public Foo Foo() {
      return Foo();
   }
}

Bạn có thể, mà không cần kéo dài quá nhiều trí tưởng tượng, dễ dàng kết thúc bằng một cuộc gọi đệ quy vô hạn. Trình biên dịch sẽ phải thực thi một lỗi "Tên hàm giống như đối tượng". Điều này thực sự sẽ không gây hại, nhưng nó đơn giản hơn nhiều để sử dụng new, trong đó tuyên bố, Go to the object of the same name as this method and use the method that matches this signature.Java là một ngôn ngữ rất đơn giản để phân tích và tôi nghi ngờ điều này hỗ trợ trong lĩnh vực đó.


1
Làm thế nào là điều này khác với bất kỳ đệ quy vô hạn khác?
DeadMG

Đó là một minh họa khá tốt về một điều tồi tệ có thể xảy ra, mặc dù nhà phát triển làm điều đó sẽ có một số vấn đề nghiêm trọng về tinh thần.
Tjaart

10

Java, đối với một, vẫn có sự phân đôi của C ++: không hoàn toàn mọi thứ là một đối tượng. Java có các kiểu dựng sẵn (ví dụ, charint) không phải được phân bổ động.

Điều đó không có nghĩa là điều đó newthực sự cần thiết trong Java - tập hợp các loại không cần phân bổ động được cố định và biết. Khi bạn xác định một đối tượng, trình biên dịch có thể biết (và trên thực tế, có biết) liệu đó có phải là một giá trị đơn giản charhay một đối tượng phải được phân bổ động.

Tôi sẽ không kiềm chế (một lần nữa) về việc điều này có nghĩa gì về chất lượng thiết kế của Java (hoặc thiếu nó, như trường hợp có thể).


Hơn nữa, các kiểu nguyên thủy hoàn toàn không cần bất kỳ lệnh gọi hàm tạo nào - chúng được viết dưới dạng chữ, đến từ một toán tử hoặc từ một hàm trả về nguyên thủy nào đó. Bạn thực sự cũng tạo ra các chuỗi (nằm trên heap) mà không có a new, vì vậy đây không thực sự là lý do.
Paŭlo Ebermann

9

Trong JavaScript, bạn cần nó bởi vì hàm tạo trông giống như một hàm bình thường, vậy làm thế nào để JS biết rằng bạn muốn tạo một đối tượng mới nếu nó không dành cho từ khóa mới?


4

Điều thú vị là, VB không cần nó - sự khác biệt giữa

Dim f As Foo

khai báo một biến mà không gán nó, tương đương với Foo f;trong C # và

Dim f As New Foo()

trong đó khai báo biến và gán một thể hiện mới của lớp, tương đương với var f = new Foo();trong C #, là một sự khác biệt đáng kể. Trong VB trước-.NET, bạn thậm chí có thể sử dụng Dim f As Foohoặc Dim f As New Foo- vì không có quá tải cho các hàm tạo.


4
VB không cần phiên bản tốc ký, nó chỉ là viết tắt. Bạn cũng có thể viết phiên bản dài hơn với loại và hàm tạo Dim f As Foo = New Foo (). Với Option Infer On, đây là thứ gần nhất với var của C #, bạn có thể viết Dim f = New Foo () và trình biên dịch sẽ nhập vào loại f.
MarkJ

2
... và Dim f As Foo()tuyên bố một mảng của Foos. Oh niềm vui! :-)
Heinzi

@MarkJ: Trong vb.net, tốc ký là tương đương. Trong vb6, nó đã không. Trong vb6, Dim Foo As New Barsẽ tạo ra Foomột thuộc tính có hiệu quả Barnếu nó được đọc trong khi (tức là Nothing). Hành vi này không bị giới hạn xảy ra một lần; thiết lập Foođể Nothingrồi đọc nó sẽ tạo ra một mới Bar.
supercat

4

Tôi thích rất nhiều câu trả lời và chỉ muốn thêm vào câu này:
Nó giúp cho việc đọc mã dễ dàng hơn
Không phải tình huống này sẽ xảy ra thường xuyên, nhưng hãy xem xét bạn muốn có một phương thức trong tên của một động từ có cùng tên với một danh từ. C # và ngôn ngữ khác tự nhiên có từ objectdành riêng. Nhưng nếu nó không phải Foo = object()là kết quả của cuộc gọi phương thức đối tượng hoặc nó sẽ bắt đầu một đối tượng mới. Hy vọng rằng ngôn ngữ không có newtừ khóa sẽ bảo vệ chống lại tình huống này, nhưng do có yêu cầu của newtừ khóa trước khi gọi hàm tạo, bạn cho phép tồn tại một phương thức có cùng tên với một đối tượng.


4
Có thể cho rằng, phải biết đây là một dấu hiệu xấu.
DeadMG

1
@DeadMG: “Có thể cho rằng” có nghĩa là “Tôi sẽ tranh luận rằng cho đến khi thanh đóng cửa” ...
Donal Fellows

3

Có rất nhiều công cụ lịch sử trong nhiều ngôn ngữ lập trình. Đôi khi nó ở đó theo thiết kế (C ++ được thiết kế để tương thích nhất có thể với C), đôi khi, nó chỉ ở đó. Đối với một ví dụ nghiêm trọng hơn, hãy xem xét switchtuyên bố C bị hỏng lan truyền bao xa .

Tôi không biết Javascript và C # đủ tốt để nói, nhưng tôi không thấy lý do nào newtrong Java ngoại trừ việc C ++ có nó.


Tôi nghĩ rằng JavaScript được thiết kế để "trông giống như Java" càng nhiều càng tốt, ngay cả khi nó đang làm một cái gì đó đặc biệt không giống Java. x = new Y()trong JavaScript không nhanh chóng các Ylớp, vì JavaScript không các lớp học. Nhưng nó trông giống như Java vì vậy nó mang newtừ khóa chuyển tiếp từ Java, tất nhiên nó mang từ khóa chuyển tiếp từ C ++.
MatrixFrog

+1 cho công tắc bị hỏng (với hy vọng bạn sửa chữa nó: D).
maaartinus

3

Trong C #, nó cho phép các kiểu hiển thị trong ngữ cảnh nơi chúng có thể bị che khuất bởi một thành viên. Cho phép bạn có một thuộc tính có cùng tên với loại của nó. Hãy xem xét những điều sau đây,

class Address { 
    public string Street { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

class Person {
    public string Name { get; set; }
    public Address Address { get; set; }

    public void ChangeStreet(string newStreet) {
        Address = new Address { 
            Street = newStreet, 
            City = Address.City,
            State = Address.State,
            Zip = Address.Zip
        };
    }
}

Lưu ý việc sử dụng newcho phép rõ ràng đó AddressAddressloại không phải là Addressthành viên. Điều này cho phép một thành viên có cùng tên với loại của nó. Nếu không có điều này, bạn sẽ cần phải thêm tiền tố vào tên của loại để tránh xung đột tên, chẳng hạn như CAddress. Điều này rất có chủ ý vì Anders không bao giờ thích ký hiệu hay bất cứ thứ gì tương tự và muốn C # có thể sử dụng được nếu không có nó. Thực tế nó cũng quen thuộc là một phần thưởng gấp đôi.


w00t và Địa chỉ sau đó có thể xuất phát từ một giao diện gọi là Địa chỉ .. chỉ, không, không thể. Vì vậy, nó không có nhiều lợi ích, có thể sử dụng lại cùng tên và giảm từ khả năng đọc chung của mã của bạn. Vì vậy, bằng cách giữ I cho các giao diện, nhưng loại bỏ C khỏi các lớp, chúng chỉ tạo ra mùi khó chịu không có lợi ích thiết thực.
gbjbaanb

Tôi tự hỏi rằng họ không sử dụng "Mới" thay vì "mới". Ai đó có thể nói với họ rằng cũng có những chữ cái viết thường, giải quyết vấn đề này.
maaartinus

Tất cả các từ dành riêng trong các ngôn ngữ dẫn xuất C, chẳng hạn như C #, là chữ thường. Ngữ pháp yêu cầu một từ dành riêng ở đây để tránh sự mơ hồ do đó sử dụng "mới" thay vì "Mới".
chuckj

@gbjbaanb Không có mùi. Nó luôn luôn rõ ràng cho dù bạn đang đề cập đến một loại hoặc một tài sản / thành viên hoặc một chức năng. Mùi thực sự là khi bạn đặt tên cho một không gian tên giống như một lớp. MyClass.MyClass
Stephen

0

Thật thú vị, với sự ra đời của chuyển tiếp hoàn hảo, không phải newlà vị trí hoàn toàn không cần thiết trong C ++. Vì vậy, có thể nói, nó không còn cần thiết trong bất kỳ ngôn ngữ nào được đề cập.


4
Bạn chuyển tiếp để làm gì? Cuối cùng, std::shared_ptr<int> foo();sẽ phải gọi new intbằng cách nào đó.
MSalters

0

Tôi không chắc liệu các nhà thiết kế Java có suy nghĩ này hay không nhưng khi bạn nghĩ về các đối tượng là các bản ghi đệ quy , thì bạn có thể tưởng tượng rằng Foo(123)nó không trả về một đối tượng mà là một hàm có điểm cố định là đối tượng được tạo ra (nghĩa là hàm sẽ trả về đối tượng nếu nó được đưa ra làm đối số thì đối tượng đang được xây dựng). Và mục đích của newviệc "thắt nút" và trả lại điểm cố định đó. Nói cách khác, newsẽ làm cho "đối tượng tương lai" nhận thức được nó self.

Cách tiếp cận này có thể giúp chính thức hóa việc thừa kế chẳng hạn: bạn có thể mở rộng một hàm đối tượng với một hàm đối tượng khác và cuối cùng cung cấp cho chúng chung selfbằng cách sử dụng new:

cp = new (Colored("Blue") & Line(0, 0, 100, 100))

Ở đây &kết hợp hai hàm đối tượng.

Trong trường hợp này newcó thể được định nghĩa là:

def new(objectFunction) {
    actualObject = objectFunction(actualObject)
    return actualObject
}

-2

Để cho phép 'không'.

Cùng với phân bổ dựa trên heap, Java chấp nhận sử dụng các đối tượng không. Không chỉ là một vật phẩm, mà là một tính năng. Khi các đối tượng có thể có trạng thái không, thì bạn phải tách khai báo khỏi khởi tạo. Do đó từ khóa mới.

Trong C ++, một dòng như

Person me;

Sẽ ngay lập tức gọi hàm tạo mặc định.


4
Ừm, có gì sai với Person me = Nilhoặc có Person meNil theo mặc định và sử dụng Person me = Person()cho không phải Nil? Quan điểm của tôi là dường như Nil không phải là nhân tố trong quyết định này ...
Andres F.

Bạn có một điểm. Người tôi = Người (); sẽ làm việc tốt như nhau.
Kris Van Bael

@AresresF. Hoặc thậm chí đơn giản hơn với Person meviệc không và Person me()gọi hàm tạo mặc định. Vì vậy, bạn luôn cần có dấu ngoặc đơn để gọi bất cứ thứ gì, và do đó loại bỏ một bất thường C ++.
maaartinus

-2

Lý do tại sao Python không cần nó là vì hệ thống loại của nó. Về cơ bản, khi bạn nhìn thấy foo = bar()trong Python, không quan trọng bar()là phương thức nào đang được gọi, một lớp đang được khởi tạo hay một đối tượng functor; trong Python, không có sự khác biệt cơ bản giữa hàm functor và hàm (vì các phương thức là các đối tượng); và bạn thậm chí có thể lập luận rằng một lớp được khởi tạo là một trường hợp đặc biệt của functor. Do đó, không có lý do gì để tạo ra sự khác biệt giả tạo trong những gì đang xảy ra (đặc biệt là vì việc quản lý bộ nhớ cực kỳ ẩn trong Python).

Trong một ngôn ngữ có hệ thống gõ khác nhau, hoặc trong đó các phương thức và lớp không phải là đối tượng, có khả năng có sự khác biệt về khái niệm mạnh hơn giữa việc tạo một đối tượng và gọi một hàm hoặc hàm functor. Do đó, ngay cả khi trình biên dịch / trình thông dịch không cần newtừ khóa, có thể hiểu rằng nó có thể được duy trì bằng các ngôn ngữ chưa phá vỡ tất cả các ranh giới mà Python có.


-4

Thực tế trong Java có một sự khác biệt khi sử dụng Chuỗi:

String myString = "myString";

la khac nhau tư

String myString = new String("myString");

Giả sử chuỗi "myString"chưa từng được sử dụng trước đó, câu lệnh đầu tiên tạo một đối tượng Chuỗi đơn trong nhóm Chuỗi (một vùng đặc biệt của vùng heap) trong khi câu lệnh thứ hai tạo hai đối tượng, một trong vùng heap bình thường cho các đối tượng và đối tượng khác trong nhóm Chuỗi . Một điều khá rõ ràng là câu lệnh thứ hai là vô dụng trong kịch bản cụ thể này, nhưng được ngôn ngữ cho phép.

Điều này có nghĩa là đảm bảo mới rằng đối tượng được tạo trong khu vực đặc biệt của heap, được phân bổ cho khởi tạo đối tượng bình thường, nhưng có thể có các cách khác để khởi tạo đối tượng mà không có nó; một ở trên là một ví dụ, và còn chỗ để mở rộng.


2
Nhưng đây không phải là câu hỏi. Câu hỏi là "tại sao không String myString = String("myString");?" (lưu ý sự vắng mặt của newtừ khóa)
Andres F.

@AresresF. Một loại imho rõ ràng ... thật hợp pháp khi có một phương thức có tên là Chuỗi trả về một Chuỗi trong một lớp Chuỗi và phải có sự khác biệt giữa việc gọi nó và gọi hàm tạo. Một cái gì đó giống nhưclass MyClass { public MyClass() {} public MyClass MyClass() {return null;} public void doSomething { MyClass myClass = MyClass();}} //which is it, constructor or method?
m3th0dman

3
Nhưng nó không rõ ràng. Đầu tiên, có một phương thức thông thường được đặt tên Stringđi ngược lại các quy ước kiểu Java, vì vậy bạn có thể giả sử bất kỳ phương thức nào bắt đầu bằng chữ hoa là một hàm tạo. Và thứ hai, nếu chúng ta không bị ràng buộc bởi Java, thì Scala có "các lớp trường hợp" trong đó hàm tạo trông giống hệt như tôi đã nói. Vậy vấn đề nằm ở đâu?
Andres F.

2
Xin lỗi, tôi không làm theo lập luận của bạn. Bạn đang tranh luận một cách hiệu quả cú pháp , không phải ngữ nghĩa và dù sao câu hỏi là về newcác ngôn ngữ được quản lý . Tôi đã chỉ ra rằng newkhông cần thiết chút nào (ví dụ Scala không cần nó cho các lớp tình huống) và cũng không có sự mơ hồ (vì dù sao bạn hoàn toàn không thể có một phương thức có tên MyClasstrong lớp MyClass). Không có sự mơ hồ cho String s = String("hello"); nó không thể là gì khác ngoài một nhà xây dựng. Và cuối cùng, tôi không đồng ý: các quy ước mã ở đó để tăng cường và làm rõ cú pháp, đó là những gì bạn đang tranh luận!
Andres F.

1
Vì vậy, đó là lý lẽ của bạn? "Các nhà thiết kế Java cần newtừ khóa vì nếu không cú pháp của Java sẽ khác"? Tôi chắc rằng bạn có thể thấy điểm yếu của lập luận đó;) Và vâng, bạn tiếp tục thảo luận về cú pháp, không phải ngữ nghĩa. Ngoài ra, tương thích ngược với những gì? Nếu bạn đang thiết kế một ngôn ngữ mới, chẳng hạn như Java, bạn đã không tương thích với C và C ++!
Andres F.

-8

Trong C # mới rất quan trọng để phân biệt giữa các đối tượng được tạo trên ngăn xếp so với heap. Chúng tôi thường xuyên tạo các đối tượng trên ngăn xếp để có hiệu suất tốt hơn. Hãy xem, khi một đối tượng trên ngăn xếp vượt ra khỏi phạm vi, nó sẽ biến mất ngay lập tức khi ngăn xếp làm sáng tỏ, giống như một nguyên thủy. Không cần người thu gom rác theo dõi nó và không có thêm chi phí quản lý bộ nhớ để phân bổ không gian cần thiết trên heap.


5
Thật không may, bạn nhầm lẫn C # với C ++.
gbjbaanb
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.