Существует ли загрязнение пространства имен в Java или С# (например, на С++)?

Я был озадачен концепцией того, как Java и С# обрабатывают пространства имен.

Во-первых, примеры загрязнения пространства имен на некоторых языках программирования:

При использовании класса Python мне сказали, что выполнение этого не рекомендуется, поскольку оно загрязняет пространство имен и, во-первых, позволяет получить доступ ко всем методам в математической библиотеке без Math.functionname, но может вызвать столкновение при написании метода с дублирующимся именем, Это также, по-видимому, вызывает больше работы для интерпретатора, поскольку он импортирует все функции, даже те, которые не используются.

  1. открыть модуль в Ocaml Выполнение этого на верхнем уровне или в файлах ML Может также вызвать конфликты в именовании. Особенно, если вы пишете библиотеку.

  2. Ограничение пространства имен JavaScript

Вопрос:

Существует ли "загрязнение пространства имен" (т.е. импортирование тонны методов, которые потенциально могут вызвать конфликт при написании методов) на С# и Java (они во многом похожи)? Почему бы и нет?

И, конечно, связанные вопросы, которые слишком похожи, задают другой вопрос:

- Это потому, что, возможно, мы должны явно @Override вещи или там какая-то превентивная мера?

-Or существует, но это не вещь, потому что она не вызывает столько хаоса, как "использование пространства имен std", и что я не знаю, что он относительно новичок в разработке программного обеспечения из академических классов?

Пример

Я обнаружил, что using много библиотек в С#, чтобы избежать повторного ввода пространств имен для переменной, например XElement

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//the ones above are auto-generated by Visual Studio, too

using System.Xml.Linq;

избежит меня делать System.Xml.Linq.XElement каждый раз, когда я создаю XElement. Как и нам всегда нужно делать std::cout в С++

или на Java, где я обычно вижу: import java.util.linkedlist, даже import java.util.*

Не будет ли это причиной загрязнения пространства имен, если мой класс используется в другом месте? Или это потому, что они будут "загрязнять" эту конкретную область класса, а не в других классах, которые могли бы импортировать или наследовать мой класс?

Я попытался найти ответ, но не смог найти его для этого, я мог бы неправильно формулировать поиск.

РЕДАКТИРОВАТЬ 4/20/2015:

Как упоминалось @RealSkeptic, выясняется, что импорт шаблонов Java также не рекомендуется. источник

В дополнение к принятому ответу и ответам ниже, импорт в Java и С# содержится внутри самих себя, поэтому даже если кто-то использует подстановочный вид импорта, который добавляет неиспользуемые имена методов в пространство имен, это не влияет на другие классы. На уровне класса, если происходит столкновение в именах, компиляторы Java и С# выдают ошибку, ссылаясь на неоднозначные импортные данные и не могут компилироваться до тех пор, пока проблема не будет решена (например, путем переименования функций).

Ответы

Ответ 1

Как уже отмечалось другими, проблема загрязнения пространства имен не столь заметна на Java, как на С++. Основная причина, по которой загрязнение пространства имен является проблемой в С++ (и, в первую очередь, называется "загрязнением" ), заключается в том, что это может вызвать ошибки в других модулях. Это объясняется более подробно в Почему "using namespace std;" считается плохой практикой?.

(В связи с этим речь здесь идет о том, что это может относиться не только к ошибкам компиляции: для компиляции ошибок вы вынуждены что-то делать и разрешать неоднозначность. Действительно, дело в том, что это может привести к правильной компиляции кода, но потом просто вызовите неправильные функции!)


В Java каждый import влияет только на файл, в котором он содержится. Это означает, что вышеупомянутое загрязнение может все же происходить локально в одном файле. (Можно сказать: это только проблема автора, который фактически вызвал загрязнение пространства имен, что справедливо)

Аналогично случаю в вышеупомянутой ссылке: представьте, что вы используете две библиотеки: "foo" и "bar". И из лени (или отсутствия знаний о передовых методах) вы используете импорт подстановочных знаков:

import foo.*:
import bar.*:

class MyClass {
    void someMethod() {

        // Assume that this class is from the "foo" librariy, and the
        // fully qualified name of this class is "foo.Example"
        Example e = new Example();
    }
}

Теперь представьте, что вы обновляете свою версию библиотеки "bar". И новая версия содержит класс под названием bar.Example. Тогда приведенный выше код не скомпилируется, потому что ссылка на класс Example неоднозначна.

Та же проблема может, кстати, также появляться с статическим импортом. Это немного более тонкий и тонкий, и коллизии немного более вероятны. Вот почему они говорят, что вы должны использовать статический импорт очень экономно.


Замечание: Конечно, эти столкновения и двусмысленности могут быть легко решены. Вместо этого вы можете использовать только полные имена. Большинство современных Java IDE предлагают функциональность для организации/оптимизации импорта. Например, в Eclipse вы всегда можете нажать CTRL + Shift + O, который (в зависимости от настроек в Preferences- > Java- > Code Style- > Organize Imports) заменит все подстановочные импорты на индивидуальные из них.

Ответ 2

Я думаю, что у Java/С# есть разные философы, чем на С++. Позвольте мне объяснить.

Когда вы импортируете что-то в Java, вы импортируете его только в эту часть кода. Скажем, у вас есть класс A в пакете packageA. Кроме того, A импортирует класс B в пакет packageB и B import java.util.LinkedList. В С++ A будет включать заголовочный файл для использования B, и в этом заголовочном файле у вас будет #include для некоторого LinkedList. Таким образом, LinkedList будет отображаться в A. В Java это не так: class A должен включать java.util.LinkedList самостоятельно, чтобы иметь возможность использовать его. Тем не менее, вы все равно можете получить загрязнение пространства имен, но они более локальные (обычно для каждого файла). Это причина, почему вы должны избегать звездочки при использовании import.

Я не могу дать квалифицированный ответ для С#, так как я его не использую, но я думаю, что их философия подобна.

Ответ 3

Я думаю, что в Java и С# импорт является короткой, но компилятор распознает каждую ссылку в классе с полным именем. Таким образом, вы пишете new LinkedList<>(), но компилятор понимает, что в этом классе в это время вы имеете в виду new java.util.LinkedList.LinkedList<>().

Это решает проблему, о которой вы говорили, я считаю, так как полное имя класса с пакетом абсолютно должно быть уникальным.

Ответ 4

Каждый загрузчик классов в вашей рабочей программе Java поддерживает собственное имя-пространство, которое заполняется именами всех классы.

A name-space - это набор уникальных имен для loaded classes, который поддерживается Java Virtual Machine. Например, как только a Java Virtual Machine загрузил класс с именем Volcano в конкретный name-space, невозможно загрузить другой класс с именем Volcano в тот же name-space. Однако вы можете загружать несколько классов Volcano в Java Virtual Machine, потому что вы можете создать multiple name-spaces внутри a Java application, создав несколько class loaders. Если вы создаете три отдельных пространства имен (по одному для каждого из трех загрузчиков классов) в запущенном Java application, то, загрузив один класс Volcano в каждое пространство имен, ваша программа может загрузить три разных класса Volcano в ваше приложение.

Если вы используете тот же класс-загрузчик для всех классов в вашем приложении, то все classes будут загружены только в same name space. Class Loader не будет загружать все эти classes в последующий доступ. также classes в одном name space не может взаимодействовать с классами в других name space.