2013-07-02 8 views
7

Java verfügt über spezielle Marker für die Methoden synthetic und bridge.Kann eine synthetische oder eine Bridge-Methode verwendet werden, um eine int -> doppelte API-Änderung zu glätten?

JLS 13.1.7 „Alle von einem Java-Compiler eingeführt Konstrukte, die als synthetische markiert werden ... nicht über ein entsprechendes Konstrukt in den Quellcode haben muss“

So Synthesemethoden sind alles generiert durch den Compiler und nicht im Quellcode dargestellt, und obwohl es nicht in dieser Spezifikation PDF sehr gut erwähnt wird, Brücke Methoden werden verwendet, um Generika zu schreiben. (Z Animal.interactWith(Creature c) bekommt eine Brücke Methode interactWith(Object c), die Kreatur wirft und ruft die andere Methode.)


Wir haben diese API genannt Bukkit, die stabilen Zugang bietet zu ändern, wie ein Server funktioniert Minecraft. Eine Facette der zugrunde liegenden Implementierung der API (alias vanilla Minecraft), auf die wir wenig Einfluss haben, wurde kürzlich in der Version 1.6.1 gezwungen, von Integer-Werten zu Float-Werten zu wechseln. Im Interesse, die Schwierigkeit einer weiteren Änderung zu vermeiden, haben wir alle unsere API-Methoden auf double s geändert.

So zum Beispiel:

public int getHealth(); 
public void setHealth(int health); 
// Must now be 
public double getHealth(); 
public void setHealth(double health); 

Aber wie immer, wir würden Plugins mit der vorherige Version kompilierten mögen, 1.5.2, noch so viel wie möglich arbeiten -, dass der ganze Sinn der API ist.

Die setHealth ist ein gelöstes Problem, nur eine Überlastung einführen. Und derzeit haben wir eine Methode mit dem Namen , die bei der Implementierung kompiliert wird (nicht API kompiliert) zu getHealth(V)I, und das lässt die alten Plugins weiter ausgeführt werden.

Wenn jedoch jemand versucht, unsere Implementierung dieser umbenannten Methoden zu erweitern, erhalten sie Kompilierungsfehler von den doppelt benannten Methoden und überschreiben.

Gibt es eine Möglichkeit, sowohl die int und double kehrt, um eine manuell/Werkzeug eingefügt synthetische oder Brückenmethode verwenden, , die nicht Kompilierungsfehlern für diejenigen, die versuchen, zu ändern, Teile unserer API-Implementierung verursachen ?

+1

Warum benennen Sie die Methode nicht anders und verachten das Original einfach (oder lassen es sogar veraltet) und lassen es einfach den doppelten Wert auf int gerundet zurückgeben? –

+0

@ increment1 Ich stimme dir zu, wie du nur den Namen ändern solltest ... Ich kann mich nicht erinnern, was für ein Bukkit-Objekt es war, aber ich erinnere mich an Methoden wie '_INVALID_setHealth (int i)' und 'setHealth (double d)' – Jojodmo

+0

@Jojodmo Ich denke, ich sollte eine Antwort schreiben ... (Affirmative, synthetische + Brücke ist, was Sie eine Unterklasse kompilieren müssen) – Riking

Antwort

2

Die Antwort ist ja - wenn Sie eine Methode mit unterschiedlichen Rückgabetyp markieren, aber die gleichen Parameter wie sowohl synthetische als auch Brücke, können Sie Subklassen kompilieren.

In diesem speziellen Fall wurde ein neues Maven-Dienstprogramm, "Overmapper", erstellt, um diese Aufgabe auszuführen, obwohl Sie dies in jedem automatisierten Tool tun könnten, das Java-Bytecode bearbeiten kann.Hier ist die Konfigurationsdatei:

members: 
    "org/bukkit/entity/Damageable _INVALID_damage (I)V": damage 
    "org/bukkit/entity/Damageable _INVALID_damage (ILorg/bukkit/entity/Entity;)V": damage 
    "org/bukkit/entity/Damageable _INVALID_getHealth()I": getHealth 
    "org/bukkit/entity/Damageable _INVALID_setHealth (I)V": setHealth 
    "org/bukkit/entity/Damageable _INVALID_getMaxHealth()I": getMaxHealth 
    "org/bukkit/entity/Damageable _INVALID_setMaxHealth (I)V": setMaxHealth 
    "org/bukkit/entity/LivingEntity _INVALID_getLastDamage()I": getLastDamage 
    "org/bukkit/entity/LivingEntity _INVALID_setLastDamage (I)V": setLastDamage 
    "org/bukkit/event/entity/EntityDamageEvent _INVALID_getDamage()I": getDamage 
    "org/bukkit/event/entity/EntityDamageEvent _INVALID_setDamage (I)V": setDamage 
    "org/bukkit/event/vehicle/VehicleDamageEvent _INVALID_getDamage()I": getDamage 
    "org/bukkit/event/vehicle/VehicleDamageEvent _INVALID_setDamage (I)V": setDamage 
    "org/bukkit/event/entity/EntityRegainHealthEvent _INVALID_getAmount()I": getAmount 
    "org/bukkit/event/entity/EntityRegainHealthEvent _INVALID_setAmount (I)V": setAmount 
    "org/bukkit/entity/Minecart _INVALID_getDamage()I": getDamage 
    "org/bukkit/entity/Minecart _INVALID_setDamage (I)V": setDamage 
    "org/bukkit/entity/Projectile _INVALID_getShooter()Lorg/bukkit/entity/LivingEntity;": getShooter 
    "org/bukkit/entity/Projectile _INVALID_setShooter (Lorg/bukkit/entity/LivingEntity;)V": setShooter 
    "org/bukkit/Bukkit _INVALID_getOnlinePlayers()[Lorg/bukkit/entity/Player;": getOnlinePlayers 
    "org/bukkit/Server _INVALID_getOnlinePlayers()[Lorg/bukkit/entity/Player;": getOnlinePlayers 
flags: 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity getHealth()I": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftEnderDragonPart getHealth()I": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity getMaxHealth()I": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftEnderDragonPart getMaxHealth()I": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity setHealth (I)V": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftEnderDragonPart setHealth (I)V": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity setMaxHealth (I)V": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftEnderDragonPart setMaxHealth (I)V": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity damage (I)V": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftEnderDragonPart damage (I)V": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity damage (ILorg/bukkit/entity/Entity;)V": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftEnderDragonPart damage (ILorg/bukkit/entity/Entity;)V": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity getLastDamage()I": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftLivingEntity setLastDamage (I)V": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftMinecart setDamage (I)V": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftMinecart getDamage()I": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftProjectile getShooter()Lorg/bukkit/entity/LivingEntity;": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftProjectile setShooter (Lorg/bukkit/entity/LivingEntity;)V": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftArrow getShooter()Lorg/bukkit/entity/LivingEntity;": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftArrow setShooter (Lorg/bukkit/entity/LivingEntity;)V": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftFireball getShooter()Lorg/bukkit/entity/LivingEntity;": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftFireball setShooter (Lorg/bukkit/entity/LivingEntity;)V": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftFish getShooter()Lorg/bukkit/entity/LivingEntity;": 0x1001 
    "org/bukkit/craftbukkit/v${minecraft_version}/entity/CraftFish setShooter (Lorg/bukkit/entity/LivingEntity;)V": 0x1001 

Sie können sehen, dass alle int-Rückkehr Methoden geändert werden als Brücke und synthetische gekennzeichnet werden.

-1

Wenn Sie etwas mit einem Entitätszustand machen möchten, können Sie in eine Damageable einwerfen und dann wird es keinen Kompilierungsfehler mehr geben.

Entity e = /* some entity */; 
double health = ((Damageable) e).getHealth(); 

Dies sollte funktionieren. Ich hoffe, es half

+2

Diese Frage ist von einer API-Erstellung Standpunkt, nicht eine API-Nutzung Standpunkt. Das Plugin-Entwickler-Update soll bukkit.jar höher in Ihre Abhängigkeitsliste stellen. – Riking