Co chciałbym móc zrobić, to załadować zestaw klas, prawdopodobnie wszystkie w tym samym folderze. Wszystkie implementują ten sam interfejs i są tej samej klasy, wtedy w moim kodzie chciałbym móc wywoływać funkcje na tych klasach.Java: Dynamicznie ładuj wiele wersji tej samej klasy.
Odpowiedz
oparciu o odpowiedź na moje pytanie, wydaje chcesz zdefiniować interfejs gry, a następnie podłącz w dowolnej liczbie implementacji sztucznej inteligencji, prawdopodobnie skonfigurowanej z pliku .properties. Jest to dość standardowe użycie interfejsu API.
Definiujesz interfejs EngineInterface dostarczający metodę, która akceptuje stan gry i zwraca ruch. Następnie definiujesz wiele klas, które wszystkie implementują interfejs EngineInterface. Sterownik odczytuje plik właściwości, aby uzyskać nazwy klas implementacji, tworzy je za pomocą Class.forName() i zapisuje je na liście i/lub mapie. Następnie, gdy kierowca otrzymuje żądania, po kolei wywołuje każdą implementację i śledzi wyniki.
Jeśli można użyć OSGi, jej tak proste, jak pęknięcia palca! W oSGI możesz mieć wiele wersji tej samej klasy . Wszystko, co musisz zrobić, to mieć te same pakiety w różnych wersjach.
W przeciwnym razie można nadal pisać niestandardowy program ładujący klasy, który odczytuje obie klasy. Jednym ze sposobów robienia tego byłoby właśnie to. Piszemy dwie klasy ClassLoaders, jedna z nich ładuje jedną wersję klasy, a druga ładuje drugą wersję klasy. Teraz na podstawie potrzeby wybrania klasyloader1 lub classloader2 do załadowania klasy. Teraz możesz również załadować jednocześnie wiele wersji tej samej klasy w pamięci.
Uwaga: Upewnij to faktycznie chcesz zrobić, mogą istnieć inne sposoby zbliża się wokół problemu.
mogę mieć osgi? –
@jason ... nie dostałem ciebie :) –
"tak proste jak zatrzaśnięcie palca" ... To jest odważne stwierdzenie odnośnie do OSGi. – Thilo
Jedynym ramy wiem który obsługuje co jesteś Po OSGI:
alt text http://blog.springsource.com/wp-content/uploads/2009/01/network.png
Jego model sieci, opisane w niniejszym artykule "Exposing the boot classpath in OSGi", zezwala że
Jednym z efektów ubocznych (lub celów) modelu sieciowego jest izolacja typu lub klasy: wiele wersji tej samej klasy może ładnie współegzystować wewnątrz tej samej maszyny wirtualnej, ponieważ ea ch jeden jest ładowany do własnej sieci, własnej przestrzeni.
Zobacz ten tutorial na początku i wybrać na EOF ram OSGI (jak Equinox, Knoplerfish lub Apache Felix)
Próbowałeś coś takiego:
class Move; // some data type that is able to represent the AI's move.
interface AI {
Move getMove(GameState state);
};
AIOne implements AI;
AITwo implements AI;
Każda klasa będzie realizować swój własny algorytm do generowania ruchu, ale byłoby nazwać ale wywołana przez wspólnej metody
Możliwe jest robić to, co chcesz z OSGI, ale równie dobrze możesz użyć niestandardowego programu ładującego klasy. Chodzi o to, że musisz zainicjować moduł ładujący klasy dla każdej wersji klasy, którą chcesz załadować.Here można znaleźć dobre wyjaśnienie. Ale myślę
czego naprawdę potrzebujesz, aby rozwiązać Twój problem jest coś oparte na interfejsach jak opisane przez Jim Garrison czy Dave L Delaney ...
Można to zrobić przy użyciu klasy dynamicznej załadunek. Nie ładuje klasy innej wersji, ale różni podklasy super klasy lub interfejsu.
ważne kroki to:
(1) Wykorzystanie Class.forName (...), aby załadować klasę według nazwy. Klasa musi znajdować się na ścieżce klasy.
(2) Użyj aClass.newInstance() do utworzenia instancji obiektu. Jest to łatwe, jeśli nie ma parametru wymaganego dla konstruktora.
Poniższy kod powinien dać ci pewien pomysł. Nie obsługuje wyjątków, które musisz zrobić.
class Context {
void moveUp();
void moveDown();
...
}
interface AI {
void action(Context con);
}
public class Game {
public Game() {
Context aContext = new Context();
String[] aAIClsNames = this.getAIClassNames("ai.list");
AI[] aAIs = this.loadAI(aAIClsNames);
this.run(aAIs);
}
String[] getAIClassNames(String pAIClassListFile) {
// .. Load the file containning the AI-class file names
}
AI[] loadAI(String[] pAIClsNames) {
AI[] AIs = new AI[pAIClsNames.length];
for(int i = 0; i < pAIClsNames.length; i++) {
String aAIClsName = pAIClsNames[i];
// (1) Get the class by name
Class<? extends AI> aAICls = Class.forName(aAIClsName);
// (2) Notice the cast as all of class in the list must implements AI
AIs[i] = (AI)aAICls.newInstance();
}
return AIs;
}
void run(AI[] pAIs) {
// ...
}
}
Mam nadzieję, że to pomoże.
Odpowiedź Jima jest dobra - określasz klasy, z których chcesz korzystać, i wszystkie są zgodne z typowym interfejsem API. Jednak podane rozwiązanie zakłada, że klasy są już dostępne w ścieżce klas aplikacji. Możliwe, że będziesz w stanie dodać więcej implementacji później, np. po zainstalowaniu aplikacji.
Jeśli tak jest, prawdopodobnie będziesz musiał użyć niestandardowego programu ładującego klasy. Na przykład można zezwolić użytkownikom na umieszczanie plików jar w określonym folderze i dodawanie nazw klas implementacji do pliku właściwości. Będziesz wtedy potrzebował niestandardowego programu ładującego klasy, który może załadować klasy z słoików znajdujących się w tym folderze, a ty użyjesz tego programu ładującego klasy do załadowania klas (np. Przy użyciu Class.forName (className, classLoader)).
W rzeczywistości, jeśli masz moduł ładujący klasy na plik jar, będziesz mógł mieć wiele klas o tych samych nazwach w plikach jar, ponieważ program ładujący klasy definiuje granice nazw klas. To właśnie robi OSGI.
Oto niektóre kodu odnoszące się do klas załadowczych od słoików:
http://sourceforge.net/projects/jcloader/ http://www.javaworld.com/javatips/jw-javatip70.html
- 1. Wiele wersji JQuery na tej samej stronie
- 2. Wiele wersji Delphi na tej samej maszynie
- 3. TopShelf zainstalować wiele tej samej usługi na tej samej maszynie
- 4. Ładuj jQuery dynamicznie
- 5. jQuery owinąć wiele elementów div na tej samej klasy
- 6. Wiele relacje hasMany do tej samej klasy domeny w Grails
- 7. Wiele WebRequest w tej samej sesji
- 8. Regex wiele meczów na tej samej linii
- 9. Java - gra liczbowa - wiele ActionListener w tej samej klasie
- 10. Ustal, czy dwa obiekty Java są tej samej klasy
- 11. Mockito: wiele połączeń do tej samej metody
- 12. Wiele pól do tej samej kolumny DB
- 13. Wiele połączeń socket.io na tej samej stronie
- 14. mediaelement.js Wiele filmów na tej samej stronie?
- 15. Wiele elementów iScroll na tej samej stronie
- 16. Wiele znaczników na tej samej współrzędnej
- 17. Highcharts.js - wiele motywów na tej samej stronie?
- 18. Wiele kluczy obcych do tej samej tabeli
- 19. Wiele wykresów na tej samej figurze [R]
- 20. Wiele powiadomień o tej samej aktywności
- 21. wiele tabel na tej samej linii
- 22. Wiele programów ładujących w tej samej działalności
- 23. ma_nowy związek do tej samej klasy
- 24. Shuffle wszystko div z tej samej klasy
- 25. Jak powinienem strukturyzować wiele wystąpień tej samej podklasy Ember.Application na tej samej stronie?
- 26. Czy kod Java jest kompatybilny z bajtami w ramach różnych aktualizacji tej samej wersji Java?
- 27. Dynamicznie ładuj i usuwaj arkusze stylów
- 28. Dynamicznie ładuj czcionki Google po wczytaniu strony
- 29. AngularJS: dynamicznie ładuj widok częściowy do strony
- 30. Wiele grup przycisków radiowych o tej samej nazwie
Nie jest to możliwe bez grania ze zwyczajem classloaders (a może nawet nie być możliwe). Może gdybyś wyjaśnił, co próbujesz osiągnąć, dostaniesz więcej pomocy. –
OSGI wygląda jednak bardzo interesująco, być może niewłaściwie podchodzę do tego problemu. W mniej ogólnym znaczeniu, oto, co próbuję osiągnąć. Mam powłokę gry Oware, która uruchamia mechanikę gry. Prosi inne klasy, aby wykonały swoje ruchy, wysyłając im stan gry i zwracając ruch. Chciałbym mieć folder z AI, z których każda zawiera inny kod, może być ich wiele. Powłoka będzie wtedy prowadzić turniej rundy wszystkich badanych sztuczek, które wygrali przeciwko którymś z AI. – JonLeah