Могу ли я поместить класс в объявление общего класса?

Я хочу знать, есть ли способ сделать что-то вроде этого:

  Class clazz = Class.forname ("java.lang.String");  GenericClass  generic = new GenericClass (); 

помещает класс в параметр общего класса.


Нет, не существует.

Однако, если вы знаете, что делаете, вам не нужен строго общий параметр. Вы можете использовать необработанный тип :

  GenericClass generic = new GenericClass ();  

Java использует «стирание» для реализации универсальных шаблонов — это означает, что если вы напишете что-то вроде List l = new ArrayList (); , компилятор проверит, что вы никогда не пытаетесь чтобы поместить в него все, что не является String, но затем он выбросит (сотрет) универсальные шаблоны и преобразует их в List l = new ArrayList (); .

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


Нет. Обобщения оцениваются во время компиляции, а код будет запущен позже во время выполнения.


В зависимости от того, что вы хотите сделать, ваша конкретная проблема может быть решена с помощью другого универсального метода. Например, этот метод создает List , содержащий экземпляр данного Class :

   Список  createListOf (Class  clazz) {List  result = new ArrayList  ();  result.add (clazz.newInstance ());  return result;}  

Затем его можно было бы вызвать так, не зная фактических типов:

  Class > unknownClass  = Class.forName (unknownString); List > ListOfUnknownClass = createListOf (unknownClass);  

(Без дополнительной информации я не могу сделать этот ответ более конкретным для вашей конкретной проблемы )

1



Где мне размещать функции, не относящиеся к классу?

Я работаю над проектом C ++, в котором у меня есть набор математических функций, которые я изначально написал для использования как часть класса. Однако по мере того, как я писал больше кода, я понял, что мне нужны эти математические функции везде.

Где лучше всего их разместить? Допустим, у меня есть это:

  class A {public: int math_function1 (int);  ...}  

И когда я пишу другой класс, я не могу (или, по крайней мере, я не знаю, как) использовать этот math_function1 код> в этом другом классе. Кроме того, я понял, что некоторые из этих функций на самом деле не связаны с классом A. Они казались в начале, но теперь я вижу, что они просто математические функции.

Что можно сделать в этой ситуации? Прямо сейчас я копирую их в новые классы, что, я уверен, является худшей практикой.


С ++ может иметь функции, не являющиеся методами, просто отлично, если они не принадлежат классу, не помещайте их в класс, просто помещайте их в глобальную или другую область пространства имен

  пространство имен special_math_functions//необязательно {int math_function1 (int arg  ) {//определение}}  

Зависит от того, как организован проект и какой вид шаблонов проектирования, которые вы используете, предполагая, что это строго служебный код, у вас есть следующие варианты:

  • Если вам не нужно использовать объекты для всего, вы можете сделать что-то простое, например просто поместите их все в файл без оболочки класса. Это может быть с пространством имен или без него, хотя пространство имен рекомендуется для предотвращения любых проблем в будущем.
  • Для управляемого C ++ вы можете создать статический класс, содержащий их все; однако на самом деле это не работает так же, как реальный класс, и я понимаю, что это антипаттерн C ++.
  • Если вы не используете управляемый C ++, вы можете просто использовать статические функции, чтобы получить к ним доступ и все они содержатся в одном классе. Это может быть полезно, если есть также другие функции, для которых вам может потребоваться надлежащий экземпляр объекта, также может быть анти-шаблоном.
  • Если вы хотите убедиться, что только один экземпляр объекта, содержащий функции будут существовать, тогда вы можете использовать шаблон Singleton для служебного класса, который также даст вам некоторую гибкость в будущем, поскольку теперь у вас есть доступ к нестатическим атрибутам. Это будет ограниченное использование и действительно применимо только в том случае, если вам по какой-то причине нужен объект. Скорее всего, если вы сделаете это, вы уже будете знать, почему.

Обратите внимание, что первый вариант будет лучшим выбором, а следующие три имеют ограниченную полезность. Тем не менее, вы можете столкнуться с этим только из-за того, что программисты C # или Java выполняют некоторую работу на C ++ или если вы когда-либо работали над кодом C # или Java, где использование классов является обязательным.

9


Как вы уже сказали, копирование и вставка кода — это худшая форма кода. повторное использование. Если у вас есть функции, которые не принадлежат ни к одному из ваших классов или могут использоваться в нескольких сценариях, лучшим местом для их размещения был бы вспомогательный или служебный класс. Если они не используют данные экземпляра, их можно сделать статическими, поэтому вам не нужно создавать экземпляр служебного класса для его использования.

См. Здесь обсуждение статических функции-члены в собственном C ++ и здесь для статических классов в управляемом C ++. Затем вы можете использовать этот служебный класс везде, где бы вы ни вставили свой код.

Например, в .NET такие вещи, как Min () и Max () предоставляются как статические члены в классе System.Math .

Если все ваши функции связаны с математикой, а в противном случае у вас есть гигантский класс Math , вы можете захотеть разбить его дальше и иметь классы вроде TrigonometryUtilities , EucledianGeometryUtilities и т. д.

Другой вариант — поместить общие функции в базовый класс классов, требующих указанной функциональности . Это хорошо работает, когда рассматриваемые функции должны работать с данными экземпляра, однако этот подход также менее гибкий, если вы хотите избежать множественного наследования и придерживаться только одного базового класса, потому что вы «израсходуете» свою единую базу. class, чтобы получить доступ к некоторым общим функциям.

3


Устраняет неоднозначность термина «вспомогательная функция». Одно определение — это удобная функция, которую вы все время используете, просто чтобы выполнить какую-то работу. Они могут жить в основном пространстве имен и иметь свои собственные заголовки и т. Д. Другое определение вспомогательной функции — это служебная функция для одного класса или семейства классов.

 //общий помощник  template  bool isPrinter (T & p) {return (dynamic_cast  (p))?  true: false;}//специальный помощник для принтеров пространство имен printer_utils {пространство имен HP {print_alignment_page () {printAlignPage ();}} пространство имен Xerox {print_alignment_page () {Alignment_Page_Print ();}} пространство имен Canon {print_alignment_page () {AlignPage ();  }} пространство имен Kyocera {print_alignment_page () {Align (137,4);}} пространство имен Panasonic {print_alignment_page () {exec (0xFF03);  }}}//пространство имен  

Теперь isPrinter доступен для любого кода, включая его заголовок, но print_alignment_page требуется директива using namespace printer_utils :: Xerox; . Можно также ссылаться на нее как

  Canon :: print_alignment_page ();  

для большей ясности.

C ++ STL имеет пространство имен std :: , которое охватывает почти все его классы и функции, но разбивает их по категориям на более чем 17 различных заголовков, чтобы позволить кодировщик, чтобы получить имена классов, имена функций и т. д., если они хотят писать свои собственные.

На самом деле НЕ рекомендуется использовать using namespace std; в файле заголовка или, как это часто бывает, в первой строке внутри main () . std :: состоит из 5 букв и часто кажется утомительным предисловие к функции, которую вы хотите использовать (особенно std :: cout и std :: endl !), но это служит определенной цели.

В новом C ++ 11 есть несколько подпространств имен для специальных служб, таких как

  std :: placeholder, std :: string_literals  , std :: chrono, std :: this_thread, std :: regex_constants  

, которые можно использовать для использования.

Полезный метод — композиция пространства имен . Один определяет настраиваемое пространство имен для хранения пространств имен, которые вам нужны для вашего конкретного файла .cpp , и использует его вместо группы с использованием операторов для каждой вещи в пространство имен, которое может вам понадобиться.

  #include  #include  #include  Требуется пространство имен {using std :: vector;  используя std :: string;  используя std :: cout;  using std :: endl;} int main (int argc, char * argv []) {/* с использованием пространства имен std;  *///позволит избежать всех этих отдельных предложений using,//но таким образом только они будут включены в глобальное//пространство имен.  с использованием пространства имен необходимо; //втягивает вектор композиции  str_vec;  string s ("Теперь у меня есть необходимое пространство имен");  string t («Но не те, которые у меня нет»);  str_vec.push_back (s);  str_vec.push_back (t);  cout  

Этот метод ограничивает доступ ко всему std :: namespace ( он большой! ) и позволяет писать более чистый код для наиболее распространенных строк кода, которые люди пишут чаще всего.


Возможно, вы захотите поместить его в функцию шаблона, чтобы сделать его доступным для различных типов целых чисел и/или чисел с плавающей запятой:

  template  T math_function1 (T) {..}  

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

Оцените статью
clickpad.ru
Добавить комментарий