new
Ключевые слова в языках , как Java, JavaScript и C # создают новый экземпляр класса.
Этот синтаксис, по-видимому, унаследован от C ++, где new
он используется специально для выделения нового экземпляра класса в куче и возврата указателя на новый экземпляр. В C ++ это не единственный способ создания объекта. Вы также можете создать объект в стеке, не используя new
- и на самом деле этот способ создания объектов гораздо более распространен в C ++.
Итак, исходя из фона C ++, new
ключевое слово в таких языках, как Java, Javascript и C #, показалось мне естественным и очевидным. Затем я начал изучать Python, у которого нет new
ключевого слова. В Python экземпляр создается просто путем вызова конструктора, например:
f = Foo()
Поначалу мне это показалось немного странным, пока мне не пришло в голову, что у Python нет никаких оснований для этого new
, потому что все является объектом, поэтому нет необходимости устранять неоднозначность между различными синтаксисами конструктора.
Но потом я подумал - какой смысл new
в Java? Почему мы должны говорить Object o = new Object();
? Почему не просто Object o = Object();
? В C ++ это определенно необходимо new
, так как мы должны различать распределение в куче и распределение в стеке, но в Java все объекты создаются в куче, так почему же даже есть new
ключевое слово? Тот же вопрос можно задать для Javascript. В C #, с которым я гораздо менее знаком, я думаю, что new
может иметь какую-то цель с точки зрения разграничения между типами объектов и типами значений, но я не уверен.
Несмотря на это, мне кажется, что многие языки, появившиеся после C ++, просто «унаследовали» new
ключевое слово - без особой необходимости. Это почти как рудиментарное ключевое слово . Кажется, нам это не нужно по какой-либо причине, и все же оно есть.
Вопрос: я прав по этому поводу? Или есть какая-то веская причина, которая new
должна быть в C ++ - вдохновленные языки с управлением памятью, такие как Java, Javascript и C #, но не Python?
источник
new
ключевое слово. Конечно, я хочу создать новую переменную, тупой компилятор! Хороший язык будет по - моему есть синтаксис , какf = heap Foo()
,f = auto Foo()
.f
не выходит из функции, выделяйте место в стеке.f
при возврате вмещающей функции.Ответы:
Ваши наблюдения верны. C ++ - сложный зверь, и
new
ключевое слово использовалось для того, чтобы различать что-то, что нужноdelete
позже, и то, что будет автоматически исправлено. В Java и C # они отбросилиdelete
ключевое слово, потому что сборщик мусора позаботится об этом за вас.Проблема в том, почему они сохранили
new
ключевое слово? Без разговоров с людьми, которые написали язык, трудно ответить. Мои лучшие догадки перечислены ниже:new
ключевое слово создает объект в куче. Итак, зачем менять ожидаемое поведение?В своем использовании Ruby находится где-то между Python и Java / C #
new
. По сути, вы создаете объект как этот:Это не ключевое слово, это статический метод для класса. Это означает, что если вы хотите одиночный, вы можете переопределить реализацию по умолчанию,
new()
чтобы каждый раз возвращать один и тот же экземпляр. Это не обязательно рекомендуется, но это возможно.источник
alloc
метод (примерно такой же, как у Rubynew
) также является просто методом класса.Короче говоря, вы правы. Ключевое слово new излишне в таких языках, как Java и C #. Вот некоторые идеи Брюса Экеля, который был членом C ++ Standard Comitee в 1990-х годах, а затем опубликовал книги по Java: http://www.artima.com/weblogs/viewpost.jsp?thread=260578
источник
var
Ключевое слово нигде близко , как хорошо , какauto
в C ++, но я надеюсь , что это будет улучшаться.Есть две причины, о которых я могу думать:
new
различает объект и примитивnew
Синтаксис является немного более удобным для чтения (ИМО)Первое тривиально. Я не думаю, что в любом случае сложнее отличить их друг от друга. Вторым является пример точки ОП, которая
new
является своего рода избыточной.Однако могут быть конфликты пространства имен; рассмотреть возможность:
Вы можете, не слишком напрягая воображение, легко закончить бесконечно рекурсивным вызовом. Компилятор должен будет вызвать ошибку «Имя функции совпадает с именем объекта». Это действительно не повредит, но гораздо проще в использовании
new
, в котором говорится, чтоGo to the object of the same name as this method and use the method that matches this signature.
Java - очень простой для анализа язык, и я подозреваю, что это помогает в этой области.источник
Java, например, до сих пор дихотомии C ++: не совсем все является объектом. Java имеет встроенные типы (например,
char
иint
), которые не должны быть распределены динамически.Это не означает, что
new
это действительно необходимо в Java - набор типов, которые не нужно распределять динамически, фиксирован и известен. Когда вы определяете объект, компилятор может знать (и фактически знает), является ли это простым значениемchar
или объектом, который должен быть динамически размещен.Я воздержусь (еще раз) от мнения о том, что это означает о качестве дизайна Java (или его отсутствии, в зависимости от обстоятельств).
источник
new
, так что это на самом деле не причина.В JavaScript это нужно, потому что конструктор выглядит как обычная функция, так как же JS узнает, что вы хотите создать новый объект, если бы он не был для ключевого слова new?
источник
Интересно, что это нужно VB - различие между
который объявляет переменную без ее присвоения, эквивалент
Foo f;
в C #, икоторая объявляет переменную и присваивает новый экземпляр класса, эквивалентный
var f = new Foo();
в C #, является существенным отличием. В до .NET VB вы могли даже использоватьDim f As Foo
илиDim f As New Foo
- потому что не было перегрузки конструкторов.источник
Dim f As Foo()
объявляет массив изFoo
с. О, радость! :-)Dim Foo As New Bar
было бы эффективно создатьFoo
свойство, которое могло бы создать a,Bar
если бы оно было прочитано while (то естьNothing
). Такое поведение не ограничивалось случаем один раз; установкаFoo
наNothing
а затем чтение было бы создать еще один новыйBar
.Мне нравится много ответов, и я просто хотел бы добавить следующее:
это облегчает чтение кода.
Не то чтобы такая ситуация случалась часто, но учтите, что вам нужен метод с именем глагола, который имеет то же имя, что и существительное. C # и другие языки, естественно, имеют
object
зарезервированное слово . Но если бы это было не так, это было быFoo = object()
результатом вызова метода объекта или созданием нового объекта. Надеемся, что указанный язык безnew
ключевого слова имеет защиту от этой ситуации, но, имея требованиеnew
ключевого слова перед вызовом конструктора, вы допускаете существование метода с тем же именем, что и у объекта.источник
На многих языках программирования есть много рутинных вещей. Иногда это там разработано (C ++ был разработан, чтобы быть максимально совместимым с C), иногда, это просто там. Для более вопиющего примера рассмотрим, как далеко зашло нерабочее
switch
выражение C.Я не знаю Javascript и C # достаточно хорошо, чтобы сказать, но я не вижу причин для этого
new
в Java, кроме того, что в C ++ это было.источник
x = new Y()
в JavaScript не экземпляр вY
класс, потому что JavaScript не имеет классов. Но это похоже на Java, поэтому оно переноситnew
ключевое слово вперед из Java, что, конечно, переносило его из C ++.В C # это позволяет типам, видимым в контекстах, где они могли бы быть скрыты членом. Позволяет вам иметь свойство с тем же именем, что и его тип. Рассмотрим следующее,
Обратите внимание, что использование
new
позволяет понять, чтоAddress
этоAddress
тип, а неAddress
член. Это позволяет члену иметь то же имя, что и его тип. Без этого вам потребуется префикс имени типа, чтобы избежать конфликта имен, напримерCAddress
. Это было преднамеренно, так как Андерсу никогда не нравились венгерские обозначения или что-то подобное, и они хотели, чтобы C # можно было использовать без них. То, что это было также знакомо, было двойным бонусом.источник
Интересно, что с появлением совершенной пересылки, не размещение
new
вообще не требуется в C ++. Так что, возможно, он больше не нужен ни на одном из упомянутых языков.источник
std::shared_ptr<int> foo();
придетсяnew int
как-то позвонить .Я не уверен, имели ли это в виду Java-дизайнеры, но когда вы думаете об объектах как о рекурсивных записях , вы можете представить, что
Foo(123)
не возвращает объект, а функцию, чья точка фиксации является создаваемым объектом (т. Е. Функция, которая возвращает объект, если он задан в качестве аргумента объекта, который создается). И цельnew
состоит в том, чтобы «завязать узел» и вернуть эту точку фиксации. Другими словамиnew
, «объект бытия» осознает этоself
.Такой подход может помочь, например, формализовать наследование: вы можете расширить объектную функцию другой объектной функцией и, наконец, предоставить им общее
self
с помощьюnew
:Здесь
&
сочетаются две объект-функции.В этом случае
new
может быть определено как:источник
Разрешить ноль.
Наряду с распределением на основе кучи Java включил использование объектов nil. Не просто как артефакт, а как особенность. Когда объекты могут иметь нулевое состояние, тогда вы должны отделить объявление от инициализации. Отсюда и новое ключевое слово.
В C ++ строка вроде
Будет немедленно вызвать конструктор по умолчанию.
источник
Person me = Nil
,Person me
что по умолчанию используется Nil и используетсяPerson me = Person()
для не-Nil? Моя точка зрения заключается в том, что не похоже, что Нил был фактором в этом решении ...Person me
нулем иPerson me()
вызовом конструктора по умолчанию. Таким образом, вам всегда нужны круглые скобки, чтобы вызывать что-либо и, таким образом, избавиться от одной ошибки C ++.Причина, по которой Python не нуждается в этом, заключается в его системе типов. Фундаментально, когда вы видите
foo = bar()
в Python, не имеет значения,bar()
является ли метод, который вызывается, класс, который создается, или объект функтор; в Python нет принципиальной разницы между функтором и функцией (потому что методы являются объектами); и вы можете даже утверждать, что экземпляр класса является частным случаем функтора. Таким образом, нет никакой причины создавать искусственную разницу в происходящем (особенно потому, что управление памятью в Python настолько скрыто).В языке с другой системой типирования или в котором методы и классы не являются объектами, существует более сильная концептуальная разница между созданием объекта и вызовом функции или функтора. Таким образом, даже если компилятору / интерпретатору не нужно
new
ключевое слово, понятно, что оно может поддерживаться в языках, которые не нарушают все границы, которые имеет Python.источник
На самом деле в Java есть разница при использовании строк:
отличается от
Предположим, что строка
"myString"
никогда не использовалась ранее, первый оператор создает один объект String в пуле String (специальная область кучи), а второй оператор создает два объекта, один в обычной области кучи для объектов и другой в пуле String. , Совершенно очевидно, что второе утверждение бесполезно в этом конкретном сценарии, но допустимо языком.Это означает, что new гарантирует, что объект создан в этой специальной области кучи, выделенной для обычной реализации объекта, но могут быть и другие способы создания экземпляров объекта без него; Выше приведен пример, и есть место для расширения.
источник
String myString = String("myString");
?" (обратите внимание на отсутствиеnew
ключевого слова)class MyClass { public MyClass() {} public MyClass MyClass() {return null;} public void doSomething { MyClass myClass = MyClass();}} //which is it, constructor or method?
String
противоречит соглашениям стиля Java, поэтому вы можете просто предположить, что любой метод, начинающийся с заглавной буквы, является конструктором. И во-вторых, если мы не ограничены Java, то в Scala есть «классы дел», в которых конструктор выглядит точно так, как я сказал. Так в чем же проблема?new
для управляемых языков . Я показал, чтоnew
это совсем не нужно (например, Scala не нуждается в классах кейсов), а также что нет двусмысленности (так как вы абсолютно не можете иметь метод, названныйMyClass
в классе вMyClass
любом случае). Там нет никакой двусмысленности дляString s = String("hello")
; это не может быть что-то еще, кроме конструктора. И, наконец, я не согласен: существуют соглашения по коду для улучшения и уточнения синтаксиса, о чем вы спорите!new
ключевом слове, потому что иначе синтаксис Java был бы другим»? Я уверен, что вы видите слабость этого аргумента;) И да, вы продолжаете обсуждать синтаксис, а не семантику. Также обратная совместимость с чем? Если вы разрабатываете новый язык, такой как Java, вы уже несовместимы с C и C ++!В C # new важно различать объекты, созданные в стеке, и кучу. Часто мы создаем объекты в стеке для лучшей производительности. Видите, когда объект в стеке выходит из области видимости, он немедленно исчезает, когда стек разворачивается, как примитив. Для сборщика мусора нет необходимости отслеживать его, и нет никаких дополнительных затрат менеджера памяти для выделения необходимого пространства в куче.
источник