Если я правильно помню, конкретный конкретный класс, который выбирается, определяется во время выполнения через отражение. Поскольку Minecraft не является открытым исходным кодом, все разработчики являются обфускамированными скомпилированными файлами классов для работы.
Код выполняет поиск по каждому файлу класса внутри фрейма minecraft, ищет класс, соответствующий определенным условиям, а затем, используя библиотеку байт-кода, заставляет этот класс реализовать этот интерфейс.
Например, допустим, что следующий (затемненный) класс был реальногоServer
класса в коде Minecraft
class a {
String x_x317() {
return q_q98;
}
static a a_a1;
static String q_q98 = "1.9.4";
}
В этом случае метод x_x317
возвращает строку версии. Инструмент, который позволяет им тоже вклиниться в этот класс может сделать это на основе следующих условий:
- класс имеет доступ по умолчанию
- класс имеет только один по умолчанию доступ статическую ссылку на себя
- класс имеет только одно статическое поле String по умолчанию.
- Класс имеет единственный метод, который имеет доступ по умолчанию, который возвращает
String
, а возвращаемое значение является FieldRef
найдено в 3.
Это обычно возвращает только один класс. В случае возвращения нескольких (обычно в фазе dev новой версии Bukkit) они становятся более конкретными с их условиями, чтобы гарантировать, что они вернут правильный класс. Они делают это для каждого поля, класса и метода, которые они должны идентифицировать.
Поскольку теперь они знают, какой именно класс является классом Server
, они могут идти дальше и вносить в него изменения. Во-первых, они должны были бы реализовать интерфейс
class a implements org.bukkit.Server
А затем реализовать метод
class a implements org.bukkit.Server {
String x_x317() {
return q_q98;
}
public String getVersionNumber() {
return x_x317();
}
static a a_a1;
static String q_q98 = "1.9.4";
}
Теперь у нас есть класс, который соответствует API Bukkit.
Когда им нужно создать экземпляр этого класса, они просто делают что-то вдоль линий
Server server = findAndTransformServerClassFromMinecraftJar();
// ...
Server findAndTransformServerClassFromMinecraftJar() {
// load classes from jar
// map them to the appropriate interfaces
// transform and hook the required classes and methods
Class<?> serverClass = doTheFirstThreeSteps();
return (Server) serverClass.newInstance();
}
Я подозреваю, что 'server' идет экземпляр к реализующему классу' интерфейса Server' в каком-то момент. Например: 'Bucket.server = new VersionFiveServer()' и 'VersionFiveServer реализует сервер'. – CollinD
Сервер - это интерфейс, поэтому он не будет иметь код. У него будет только подпись метода. Вот что такое интерфейс. Некоторые другие классы реализуют этот интерфейс и содержат код. – ManoDestra
Связанный: http://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface –