EnumMap with LuaJava (attempt to call a nil value) - java

As the title says, I have problem with LuaJava and EnumMap. I'm trying to do a RPG Library, so we have a Character with some Attributes and a list of them. In the code below, I'll report only important things.
I have a class called ConcreteAttribute that extends AbstractAttribute, that has a constructor with a String and two int.
public abstract class AbstractAttribute {
protected String name;
protected int baseValue;
protected double baseMolt;
public AbstractAttribute(String name, int valoreBase, double moltBase){
this.name = name;
this.baseValue = valoreBase;
this.baseMolt = moltBase;
}
/*Getters and Setters*/
}
Then I have an Enum called StatType, that represents the stat you have in RPG games:
public enum StatType {
HP, MP, Attack, Defense;
}
I have also a class called PlayableCharacter, that has (I'll report only important things):
public abstract class PlayableCharacter extends Character{
protected EnumMap<StatType, ConcreteAttribute> statistiche;
//Constructor
public EnumMap<StatType, ConcreteAttribute> getStatistiche(){
return statistiche;
}
and a "put" method from Map.
To create a new character, I'm currently doing this ("Eroe" extends PlayableCharacter):
public static void main(String[] args) {
PlayableCharacter pers = new Eroe("Eroe 1");
ConcreteAttribute atk = new ConcreteAttribute("Attacco", 20, 0);
pers.getStatistiche().put(StatType.Attacco_Fisico, atk);
}
and works fine, but I don't think it is the best solution when you have a lot of ConcreteAttribute and a lot of Character. So I was thinking to use Lua to create "concrete" istance of Character, this way (little example):
-- Eroe 1.lua
function create(eroe)
eroe:setName("Eroe 1")
attributes = luajava.bindClass("personaggi.attributi.StatType")
attacco = luajava.newInstance("personaggi.attributi.ConcreteAttribute", "Attacco", 20, 0)
eroe:getStatistiche():put(attributes.Attacco_Fisico, attacco)
end
but I get this error: PANIC: unprotected error in call to Lua API (attempt to call a nil value). The problem is with the last line, but I'm really new to Lua and I don't even know if Lua can handle EnumMap.
Any solution to this?
Thanks to all and sorry for my bad English ^^
EDIT: I've edited the code, I found an error

An enum constant is public member of its enum class, but you are accessing it like a method using :.
So instead of attributes:Attacco_Fisico you need to use attributes.Attacco_Fisico.

Related

If Downcasting Should Be Avoided, What Should I Do?

have the following interface class:
public interface IGameObject {
String gameObjectID();
String gameObjectName();
void isActionValid(String action);
void viewActions();
}
I have the following abstract class that implements the above interface.
package gameprobjectpackage;
public abstract class Weapon implements IGameObject {
//Left out getters/setters to keep it simple
private String gameOjectID;
private String gameObjectName;
private int damage;
public Weapon(String gameOjectID, String gameObjectName,int damage) {
super();
this.gameOjectID = gameOjectID;
this.gameObjectName = gameObjectName;
this.damage = damage;
}
I've come across a few posts that suggest downcasting should be avoided. I understand why, BUT, my question is what do I do if I need to access a method that is specific to a sub class. For example:
public class ChargeGun extends Weapon {
private String [] chargeGunActions;
public ChargeGun(String gameOjectID, String gameObjectName, int damage) {
super(gameOjectID, gameObjectName, damage);
chargeGunActions = new String [3];
chargeGunActions[0] = "Charge and Fire";
chargeGunActions[1] = "Release";
chargeGunActions[2] = "Drop Gun";
}
//This method is only meant for gun, and this type of gun is the only one in my game.
//This method, I don't belive should be in the abstract method weapon, because NOT every weapon is a gun.
public void reloadGun()
{
}
I store in in an interventory hashmap like so:
Map<String,IGameObject> inventory = new HashMap<String,IGameObject>();
When I retrieve it, I will get an IGameObject, how do I properly cast it, so that I can access the method in ChargeGun?
You can use the visitor pattern which frees you from casting. The idea is simple : You have an inventory of IGameObject which would have a method accept(GameObjectVisitor v) which directly calls v.visit(this). In your GameObjectVisitor, you just have to implement visit methods for each implementations : For example visit(Chargegun g), visit(Sword s), etc...
To explain it another way, it's like the principle of a boomerang : The GameObjectVisitor calls item.accept(this), and the Item implement accept(GameObjectVisitor g) with a simple g.visit(this).
By doing this, the Visitor has multiple visit methods for each implementation and can do specific stuffs without having to cast/using instanceof.

Assigning enum to Items

Some background on the project: I am attempting to craft a space/sci-fi combat sim game with tabletop rpg style dice mechanics cranked up to 11 on the complexity scale, but still being transparent about the die rolls going on under the hood. I'm currently using the Star Wars Saga Edition combat rules as a basis.
Currently I'm trying to figure out a way to assign traits to vehicle.(possibly stored as a class for each vehicle) Each trait is an enum so that it can store multiple pieces of information. Here is the code I have for size categories:
public enum VehicleSize {
LARGE(1,"Speeder bike",5),HUGE(2,"Small Fighter",10),GARGANTUAN(5,"Tank, Medium Fighter",20),COLOSSAL(10,"Imperial Walker, Light Freighter",50),
COLLOSSALfrigate(10,"Corvette, Frigate",100),COLLOSSALcruiser(10,"Imperial-class Star Destroyer, Cruiser",200),
COLLOSSALstation(10,"The Death Star, Space Station",500);
private final int refMod;
private final int threshMod;
private final String desc;
VehicleSize(int reflexModifier,String example,int thresholdModifier)
{
refMod = reflexModifier;
desc = example;
threshMod = thresholdModifier;
}
public int getRefMod() {
return refMod;
}
public String getDesc() {
return desc;
}
public int getThreshMod() {
return threshMod;
}
}
My question is such: How do create vehicle profiles in such a way that I can assign this and similar enums as traits?
For practically all purposes, a field whose type is an enum class is no different than a field of any other object type, like Integer or String.
Create a private field, add a getter and setter, or if the field is final (likely in your case, because a vehicle instance can't change its type), add it as a constructor parameter and remo e the setter.
public class Vehicle {
private final VehicleSize vehicleSize;
// other fields
public Vehicle(VehicleSize vehicleSize) {
this.vehicleSize = vehicleSize;
}
public VehicleSize getVehicleSize() {
return vehicleSize;
}
// rest of class
}
There is nothing mysterious about an enum, other than the number of different instances of it are known at compile time (and a few more things, but nothing scary).
To add this into a class, you can use it like any user defined type.
public class MyClass {
private MyEnum myEnum;
}

Java: How do I write a generic method?

let's say that I have several Creature subclasses, and that they have each have some sort of getGroup() method that returns a List<Creature>.
What I mean by "some sort of" .getGroup() method is that the name of this function varies between subclasses. For instance, Wolfs travel in packs, so they have a getPack() member. Fish travel in schools, so they have a .getSchool() member, Humans have a getFamily() member, and so on.
.getGroup() doesn not exist in Creature, and it cannot be added to the interface. None of these clases can be edited.
I'm writing a method to print the number of Creatures in their group. How would I do this?
Essentially, I'm looking to condense these two functions into the same thing:
public void PrintSchoolSize(Fish dory) {
System.out.print(dory.getSchool().size());
}
public void PrintHiveSize(Bee bee) {
System.out.print(bee.getColony().size());
}
...into the following function:
public void printGroupSize( Class<? extends Creature> cree,
FunctionThatReturnsList getGroup() ) {
System.out.print(cree.getGroup().size();
}
I'd imagine I need to pass in a second argument (function pointer?) to void printGroupSize. Any help is very appreciated, thanks!
EDIT Thank you all for the help. This is just a simplification of the real problem I'm trying to solve. Long, overly complex problems are tougher to answer, so I posed this simpler scenario.
The only answer lies in using a generic function (if that exists). The classes I'm actually working with don't have a common interface, but they all have a function that returns a List.
What you describe in your question is not much related to Java's sense of "generic methods". You could implement it with reflection (see Class.getMethod()), but I promise you that you really don't want to go there.
It would be better for Creature to declare a possibly-abstract method getGroup() that each subclass would override. You may do that in addition to providing methods with subclass-specific names, if you wish. Code that wants to obtain the group (or its size) without knowing the specific type of creature would invoke that creature's getGroup() method. That's an application of polymorphism, which seems to be what you're actually after.
If getGroup cannot be added to the Creature interface why not add another interface to your creatures?
public interface HasGroup {
Group getGroup();
}
Would mean you can create the method:
public void printGroupSize(HasGroup cree) {
System.out.print(cree.getGroup().size();
}
The simplest way is to had a getGroup() method to the Creature interface and implement it in each subclass, but it seems you cannot do that.
If you can modify the subclasses, I would actually create a new interface CreatureGroupable with a getGroupSize() and/or getGroup(). Each subclass of Creature shall implement this interface, e.g.
public interface CreatureGroupable {
CreatureGroup getGroup();
}
public enum CreatureGroup {
WOLF_PACK("pack", 30),
GEES_FLOCK("flock", 20),
FISH_SCHOOL("school", 1000),
HUMAN_FAMILY("family", 4),
...
private final String name;
private final int size;
private CreatureGroup(String name, int size) {
this.name = name;
this.size = size;
}
public String getName() { return name; }
public int getSize() { return size; }
}
public class Wolf implements Creature, CreatureGroupable {
// methods from Creature, constructor, ...
public CreatureGroup getGroup() {
return CreatureGroup.WOLF_PACK;
}
This way, if you have a List<Creature> you can access the group of each one and do whatever you have to do, e.g.
public void printGroups(List<Creature> creatures) {
for (Creature c : creatures) {
CreatureGroup group = c.getGroup();
System.out.println("A " + group.getName() +
" has roughly " group.getSize() +
" individuals.");
}
}
If you want more flexibility, you may not use an enum and just a standard interface and class hierarchy for the groups.
Thanks to everyone for the help. Since I'm not allowed to edit any of the aforementioned classes/interfaces (I can only write external functions), I wrote the following function
public List<? extends Creature> getGroup(Object obj) {
if(obj.getClass() == Bee.class)
return ((Bee)obj).getColony();
if(obj.getClass() == Fish.class)
return ((Fish) obj).getSchool();
/* repeat for the other classes */
return null;
}
...and used it here, as so:
public void printGroupSize( Class<? extends Creature> cree ) {
System.out.print(getGroup(cree).size());
}
I have verified that this solution does indeed work, since all of the get*****() functions return a List<Creature>. This solution also shrinks my codebase significantly, and is easier to maintain than the current structure.

Extending enum fields Java

I know that it isn't possible to extend enum in Java, but I am trying to find an elegant solution for the below
I am trying to model enums (or classes) which will contain http end points of various web services across regions, say I have service A and B, each will have 4 region specific end points in US, EU, JP or CN. (This is basically for some seperate debug code that I am writing, in production the end points will be picked from configuration)
I was hoping to do something like this (not compliant java code).
public enum IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public enum ServiceAEndPoint extends IEndPoint {
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
}
I could do this using interfaces where I have a method for each region, but in my opinion the enum way is more expressive, is there any better way I could model this ? What I am looking for is if there is any better way to model the inheritence relation and also having the expressive power of enumerations.
ServiceAEndPoint.NA_END_POINT
vs
serviceAEndPoint.getNAEndPoint()
I'm assuming that you will also want a ServiceBEndPoint enum (and similar). In which case I don't think your model really makes that much sense.
IEndPoint is really an enumeration of the kind of environments/regions where a service might be running. It is not an enumeration of the services themselves. Each individual service (A, B or whatever) will have different addresses for each of the regions.
Therefore I would stick with just the IEndPoint enum, and then in some service-specific code have a lookup map that will give you the address for a given end-point. Something like this:
public enum IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public class ServiceABroker {
private static final Map<IEndPoint, String> addressesByEndPoint;
static {
addressesByEndPoint = new EnumMap<>();
addressesByEndPoint.put(NA_END_POINT, "http://A.com/");
addressesByEndPoint.put(EU_END_POINT, "http://A-eu.com/");
addressesByEndPoint.put(JP_END_POINT, "http://A-jp.com/");
addressesByEndPoint.put(CN_END_POINT, "http://A-cn.com/");
}
public String getAddressForEndPoint(IEndPoint ep) {
return addressesByEndPoint.get(ep);
}
}
If these are static final constants, then just put them in an interface. Name the interface something like IServiceAEndPointKeys, where the keys part is a convention.
Here's where I consider enums to be more appropriate and useful:
Example 1: File type. An enum containing jpg, pdf etc.
Example 2: Column definitions. If I have a table with 3 columns, I would write an enum declaring ID, Name, Description (for example), each one having parameters like column header name, column width and column ID.
Im not sure I understand you question, but you can add methods to an enum for example you could do something like the following:
public enum ServiceAEndPoint{
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
private final String url;
private EndPoint(String url){
this.url=url;
}
public String getURL(){
return url;
}
}
Enums cannot be extended in such a manner, mostly because enums cannot be sub-classed or the constraints they must adhere to will not be possible to impose.
Instead leverage interfaces, like so
public interface IEndPoint;
public enum DefaultEndPoints implements IEndPoint {
NA_END_POINT,
EU_END_POINT,
JP_END_POINT,
CN_END_POINT,
}
public enum DefaultServiceEndPoints implements IEndPoint {
NA_END_POINT("http://A.com/");
EU_END_POINT("http://A-eu.com/");
JP_END_POINT("http://A-jp.com/");
CN_END_POINT("http://A-cn.com/");
}
public void doSomething(IEndPoint endpoint) {
...
}
The reason why one can't subclass in the manner you wish is related to the contract that enums will be both equal via .equals(object) and via ==. If you could subclass, would this make sense?
if ( (DefaultEndPoints)JP_END_POINT == (DefaultServiceEndPoints)JP_END_POINT) {
}
if you say "yes" then I would expect to be able to do this
DefaultEndPoint someEndpoint = DefaultServiceEndPoints.JP_END_POINT;
which would leave a door open for error, as there is no guarantee that a enum entry in one enum declaration is in the other enum declaration.
Could it be different? Perhaps, but it isn't, and changing it would definately introduce a lot of complications that would have to be thoroughly thought out (or it would open avenues to work around Java's strong static-type checking).
You may want to consider something like this:
public abstract class EndpointFactory {
public abstract String getNAEndPoint();
public abstract String getEUEndPoint();
}
public class ServiceAEndpointFactory extends EndpointFactory {
public static final String NA_END_POINT = "http://A.com/";
public static final String EU_END_POINT = "http://A-eu.com/";
public String getNAEndPoint() {
return ServiceAEndpointFactory.NA_END_POINT;
}
public String getEUEndPoint() {
return ServiceAEndpointFactory.EU_END_POINT;
}
}
public class ServiceBEndpointFactory extends EndpointFactory {
public static final String NA_END_POINT = "http://B.com/";
public static final String EU_END_POINT = "http://B-eu.com/";
public String getNAEndPoint() {
return ServiceAEndpointFactory.NA_END_POINT;
}
public String getEUEndPoint() {
return ServiceAEndpointFactory.EU_END_POINT;
}
}
Then you can refer to your strings directly like this:
ServiceAEndpointFactory.NA_END_POINT;
Or, you can use the base object if the type of service is not known until execution:
EndpointFactory ef1 = new ServiceAEndpointFactory();
String ep = ef1.getNAEndPoint();
The drawback of this is the redefinition of the get*Endpoint() functions in each sub-class. You could eliminate that by moving the static final variables to be not static in the base class and putting the getter/setter in the base class only one time. However, the drawback of that is you are not able to reference the values without instantiating an object (which essentially emulates what I find valuable with ENUMs).
How does a pattern like this appeal to you? I let the enum implement an interface and implement the interface in a Debug set and a Release set. The release set can then derive the property name from the enum name - which is neat.
public interface HasURL {
public String getURL();
}
public enum DebugEndPoints implements HasURL {
NA,
EU,
JP,
CN;
#Override
public String getURL() {
// Force debug to go to the same one always.
return "http://Debug.com/";
}
}
public enum NormalEndPoints implements HasURL {
NA,
EU,
JP,
CN;
final String url;
NormalEndPoints () {
// Grab the configured property connected to my name.
this.url = getProperty(this.name());
}
#Override
public String getURL() {
return url;
}
}

Inheritance, deriving from a derived class

I am trying to create a class from a class that is already derived from another class. (bit confusing) It adds one extra attribute in the newest "PricedApt" class that is "price". The desired constructor call is as follows
PricedApt p = new PricedApt("jill", 900, true, "jack", 1050.00);
The class is missing its constructor and im trying to create it but not sure whats wrong.
This is the (already derived (2nd) class)
public class RentalApt extends Apartment{
private String tenant;
private boolean rented;
public RentalApt(String owner, int size, boolean rented, String who){
super(owner,size);
tenant = who;
this.rented = rented;
}
My code for the (3rd) class that I have attempted is
public class PricedApt extends RentalApt {
private double price;
public PricedApt(String owner, int size, boolean rented, String who, double priceTag) {
super(owner,size,who);
price = priceTag;
}
}
Can anyone point me in the right direction as to what I am doing incorrectly? The compilation error I'm receiving is cannot find symbol (line 2 column 3).
For one, RentalApt has a four-argument constructor, but its subclass PricedApt is calling super() with only three arguments.
Try changing
super(owner,size,who);
to:
super(owner,size,rented,who);

Categories

Resources