Чтобы ответить на конкретный вопрос об использовании #include
с файлом .c
(другие ответы предлагают лучшие варианты, особенно тот, который предлагает Groo), в общем, в этом нет необходимости.
Все в файле .c
можно сделать внешне видимым и доступным, так что вы можете ссылаться на него через прототипы функций и #extern
. Так, например, вы можете сослаться на свою таблицу с помощью #extern const MyElements elems [];
в вашем основном файле .c
.
Кроме того, вы можете поместить определения в файл .h
и включить его. Это позволяет вам разделять код так, как вы хотите. Имейте в виду, что все, что делает #include
, - это вставляет содержимое включаемого файла, где находится оператор #include
, поэтому у него не должно быть какого-либо конкретного расширения файла. .h
используется по соглашению, и большинство IDE автоматически добавляют файлы .c
в список файлов для компиляции, но что касается компилятора, именование является произвольным.
Есть несколько способов решения этой проблемы. Большинство из них уже были опубликованы:
Лично я бы использовал командный подход. Команды хорошо сочетаются с шаблонными методами , позволяя вам применять определенные шаблоны для всех ваших командных объектов. Пример:
public abstract class Command {
public final Object execute(Map<String, Object> args) {
// do permission checking here or transaction management
Object retval = doExecute(args);
// do logging, cleanup, caching, etc here
return retval;
}
// subclasses override this to do the real work
protected abstract Object doExecute(Map<String, Object> args);
}
Я бы прибегал к отражению только тогда, когда вам нужно использовать этот вид сопоставления для классов, дизайн которых вы не контролируете, и для которых нецелесообразно создавать команды. Например, вы не могли открыть Java API в командной оболочке, создавая команды для каждого метода.
Как все говорили, Java не поддерживает функции как объекты первого уровня. Для этого вы используете Functor, который представляет собой класс, который обертывает функцию. У Стива Йегге отличная тирада по этому поводу.
Чтобы помочь вам с этим ограничением, люди пишут библиотеки функторов: jga , Commons Functor
К сожалению, Java не имеет функций первого класса, но учитывает следующий интерфейс:
public interface F<A, B> {
public B f(A a);
}
Это моделирует тип для функций от типа A
до типа B
, как первоклассные ценности, которые вы можете передавать. Вам нужна Map
.
Функциональная Java - это довольно полная библиотека, сосредоточенная на функциях первого класса.
В Java нет первоклассных методов, поэтому шаблон команды - ваш друг ...
дискламер: код не протестирован!
public interface Command
{
void invoke();
}
Map<String, Command> commands = new HashMap<String, Command>();
commands.put("function1", new Command()
{
public void invoke() { System.out.println("hello world"); }
});
commands.get("function1").invoke();
Вы можете использовать Map
Пример полиморфизма ..
public interface Animal {public void speak();};
public class Dog implements Animal {public void speak(){System.out.println("treat? treat? treat?");}}
public class Cat implements Animal {public void speak(){System.out.println("leave me alone");}}
public class Hamster implements Animal {public void speak(){System.out.println("I run, run, run, but never get anywhere");}}
Map<String,Animal> animals = new HashMap<String,Animal>();
animals.put("dog",new Dog());
animals.put("cat",new Cat());
animals.put("hamster",new Hamster());
for(Animal animal : animals){animal.speak();}
Как упоминалось в других вопросах, Map
с анонимными внутренними классами - это один подробный способ сделать это.
Вариантом является использование перечислений вместо анонимных внутренних классов. Каждая константа перечисления может реализовать / переопределить методы перечисления или реализованного интерфейса, почти так же, как метод анонимного внутреннего класса, но с немного меньшим беспорядком. Я считаю, что в Effective Java 2nd Ed рассматривается, как инициализировать карту перечислений. Для отображения имени перечисления просто требуется вызвать MyEnumType.valueOf (name)
.