I'd like to create an abstract super class, called Unit and give it a number of protected static fields, such as name, health, attackPower etc.
public abstract class Unit {
protected static String name;
protected static int maxHealth;
protected static int atkPower;
public String getName() {
return name;
}
}
I'd then like to create several subclasses, such as Soldier, Wizard and Tank, and statically allocate the protected field in each of the classes, so that all Soldiers have the same field values, all Wizards have the same field values, and all Tanks have the same field values. I tried something like this:
public class Soldier extends Unit {
static {
name = "Soldier";
maxHealth = 80;
atkPower = 15;
}
}
public class Wizard extends Unit {
static {
name = "Wizard";
maxHealth = 60;
atkPower = 25;
}
}
If I create a Wizard object, wizard, and then call wizard.getName() I get "Wizard". However if I then create a Soldier object, soldier, calling wizard.getName() returns "Soldier" instead. The soldier object statically overwrote the values of the variables in the wizard and soldier classes.
Wizard wizard = new Wizard();
wizard.getName(); //Wizard
Soldier soldier = new Soldier();
wizard.getName(); //Soldier
Is there any way to do what I want to do, that is keep different static values for the same variable in each subclass?
The proper way is IMHO to make getName() (same for health etc) abstract:
public abstract class Unit {
public abstract String getName();
}
and
public class Wizard extends Unit {
private static final String NAME = "Wizard";
#Override
public String getName() {
return NAME;
}
}
Don't make the members static. Make abstract methods that subclasses have to override for each of these fields. This way you also restrict access to fields that shouldn't be set again, and are only accessed in a get context:
public abstract class Unit {
public void battleCry() {
System.out.println("RAWR! I am a " + name() +
"! Tremble at my " + atkPower() +
" attack points!");
}
public abstract String name();
public abstract int maxHealth();
public abstract int atkPower();
}
And then subclasses override these:
public class Wizard extends Unit {
protected final String name = "Wizard";
#Override
public String name() {
return name;
}
#Override
public int maxHealth() {
return 60;
}
#Override
public int atkPower() {
return 25;
}
}
This makes it easier for further subclasses to override these methods as well:
public class BossWizard extends Wizard {
#Override
public String name() {
return "Boss" + super.name();
}
#Override
public int maxHealth() {
return super.maxHealth() * 2;
}
#Override
public int atkPower() {
return super.atkPower() * 2;
}
public void specialAtk() {
// Something special for the BossWizard
}
}
You can see now if you have an instance of Wizard and BossWizard respectively, the battlecry is different:
wizardInstance.battleCry(); // RAWR! I am a Wizard! Tremble at my 60 attack points!
bosswizardInstance.battleCry(); // RAWR! I am a BossWizard! Tremble at my 120 attack points!
Related
Error
public Cat (String nm, int legs, String sd, String col)
For this constructor I got following compiler error:
constructor Animal in class Animal cannot be applied to given types;
required: String, int
found: no arguments
reason: actual and formal arguments lists differ in length
Code
The parent class is right below the child class.
public class Cat extends Animal {
private String sound;
private String colour;
public Cat (String nm, int legs, String sd, String col) {
nm = super.getName();
legs = super.getNumOfLegs();
sound = sd;
colour = col;
}
public abstract class Animal {
protected String name;
protected int numOfLegs;
public Animal() {
}
public Animal(String nm, int legs) {
name = nm;
numOfLegs = legs;
}
public String getName() {
return name;
}
public int getNumOfLegs() {
return numOfLegs;
}
public abstract String display();
}
}
Should the parent abstract class be placed in a separate file instead?
I've tried that initially but it returned way more errors than it did now, especially from the abstract method display().
What is causing the error?
There are a couple of things you should change.
First of all, it is the best way to put the super class into a separate file. If you want to keep in one file you need drag it out of the Cat class and remove the scope (not public or private). But this is not a good coding style for a super class.
The next thing is, with the name/nm and legs/numOfLegs. Either you call the super constructor and provide the two variables (see my example) or you use name = nm; and numOfLegs = legs;
You should also reconsider if the name and numOfLegs varialbes need to be protected or if is fine to provide the access only through the getter.
If the number of legs, the name, sound and color will not change you could also make them immutable (with the key word final, e.g. private final String sound). If not you can make them accessible with a setter.
Finally you need to implement the abstract method in the Cat class...
public class Cat extends Animal {
private String sound;
private String colour;
public Cat(String nm, int legs, String sd, String col) {
super(nm, legs);
sound = sd;
colour = col;
}
#Override
public String display() {
return null;
}
}
abstract class Animal {
protected String name;
protected int numOfLegs;
public Animal(String nm, int legs) {
name = nm;
numOfLegs = legs;
}
public String getName() {
return name;
}
public int getNumOfLegs() {
return numOfLegs;
}
public abstract String display();
}
Suppose I have an abstract class with an abstract builder, both of which get inherited by 3 separate subclasses:
public abstract class Role {
protected string name;
protected int propertyA;
protected int propertyB;
protected abstract static class RoleBuilder<T extends Role, B extends RoleBuilder<T,B>> {
protected T role;
protected B roleBuilder;
protected abstract T getRole();
protected abstract B thisBuilder();
protected RoleBuilder(Hero h) {
role = getRole();
roleBuilder = thisBuilder();
role.name = h.name;
role.propertyA = h.propertyA;
role.propertyB = h.propertyB;
}
public T build() {
return role;
}
}
}
public class Healer extends Role {
int propertyC;
public Healer() {
}
public static final class HealerBuilder extends Role.RoleBuilder<Healer, HealerBuilder> {
#Override protected Healer getRole() {
return new Healer();
}
#Override protected HealerBuilder thisBuilder() {
return this;
}
public HealerBuilder(Hero h) {
super(h);
}
public HealerBuilder setPropertyC(int i) {
role.propertyC = i;
return roleBuilder;
}
}
}
I instantiate the healer class (and the other two subclasses) using enums methods within the enums, like so:
public enum RoleTypes {
BRUISER{
...
},
DAMAGE_DEALER {
...
},
HEALER {
public Healer getRole(Hero h) {
return new Healer.HealerBuilder(h)
.setPropertyC(h.getC);
.build();
}
};
abstract Role getRole(Hero h);
}
Where should I be validating arguments for the creation of these objects?
Within the abstract class constructor (should I validate Hero object properties, or can I assume that object is "safe" if its properties are validated on creation?) and subclass builder methods?
Within the enum methods?
Within the factory method that calls RoleType.getRole(h), used by the rest of my application to actually create objects of type Role?
I need help fixing my code with the basic concepts listed above. To save from clutter, I took a screen shot of the directions here: https://imgur.com/SdiotUi
However, when I run my code it isn't working. I know there are a lot of errors but I'm having trouble fixing them even though I've spent the past few hours googling the correct way to do this.
When I create the first constructors I am not sure if I am assigning the name and legs correctly, I am having trouble returning "true", I get an error calling the parent class taking one argument, and I don't think I am overriding the abstract class correctly.
My code:
public class Animal1 {
private String animalName;
public int numberOfLegs;
public Animal1(String name){
name = animalName;
name = "John";
}
public Animal1(String name, int legs){
name = animalName;
legs = numberOfLegs;
name = "Jack";
legs = 4;
}
public String getName(){
return animalName;
}
public int getLegs(){
return numberOfLegs;
}
public void isAMammal(){
return true;
}
public void isCarnivorous(){
return true;
}
public abstract class getHello{
}
}
public class Cat1 extends Animal1{
public Cat1(String name){
Animal1.name;
}
public abstract class getHello{
return "Meow";
}
}
public class Dog1 extends Animal1{
public Dog1(String name){
Animal1.name;
}
public abstract class getHello{
return "Woof";
}
}
public abstract class Animal1 { // If you want to have an abstract method, declare the class as abstract
private final String animalName;
private final int numberOfLegs; // better of using private and make it final since it's not going to change.
public Animal1(final String name, final int legs){ //better making the input parameters final since they are not supposed to be changed
//name = animalName;
//legs = numberOfLegs;//it assigned the field to an input parameter. that will take no effect on the object created.
animalName = name;
numberOfLegs = legs;
}
public String getName(){
return animalName;
}
public int getLegs(){
return numberOfLegs;
}
public boolean isAnimal(){ //boolean function needs a return type too!!
return true;
}
public boolean isCarnivorous(){
return true;
}
public abstract String getHello(); // an abstract method has same requirement as a normal method besides the abstract modifier. it will need a return type. And it ends with a semicolon
}
public class Cat1 extends Animal1{
public Cat1(final String name){
super(name, 4); //use super to call parent constructor
}
#Override
public String getHello(){
return "Meow";
}
}
public class Dog1 extends Animal1{
public Dog1(final String name){
super(name, 4);
}
#Override
public String getHello(){
return "Woof";
}
}
First, it looks like a few of your methods are declared as classes. I assume you wanted to make them abstract methods. They need to be changed to:
public abstract String getHello();
Note that abstract methods can only be declared in an abstract class. So, you need to redefine Animal1 as abstract.
public abstract class Animal1
Next, when you implement the abstract method, you define it as
public String getHello()
If you are using an IDE like Eclipse it will automatically offer to generate this method.
Finally, when using your constructor in your child classes like Cat1, you are trying to set "name" as if it was a static variable and bypassing the constructor you already had set for Animal1. The best way to correct this is to change the constructor in Cat1 and Dog1 to call the super constructor.
public Cat1(String name){
super(name);
}
I have an abstract class and several concrete classes which extend it.
The abstract class has two constructors. I want one of the constructors to only be callable in one particular concrete class.
(I do know about the enum pattern for Java state machines, but two levels of subclassing (and immutable POJOs) work better for the problem I'm solving.)
public abstract class SuperState {
public final long mValue;
protected SuperState(long value) { mValue = value; }
protected SuperState(SuperState last) { mValue = last.mValue + 1; }
...
}
public class FirstState extends SuperState {
public FirstState() { super(0); }
...
}
public class SecondState extends SuperState {
public SecondState(SuperState last) { super(last); }
...
}
public class ThirdState extends SuperState {
public ThirdState(SuperState last) { super(last); }
...
}
I want to make it a compile-time (or at least runtime) error for any subclass (apart from FirstState) to call the SuperState(long value) constructor.
Could I find out the type of the concrete class being constructed in the SuperState constructor, and throw a runtime exception if it's not as expected?
Is there a was of having a "preferred" concrete class for an abstract class, such that it has some form of extra access?
I think you don't know clearly what you're doing.
You're saying that SuperState has a constructor which is only callable from one specific implementation. Why? Is that subclass special? Why shouldn't other implementation call that?
If FirstState is so special, maybe you want to have it as an internal class:
public abstract class SuperState {
public final long mValue;
private SuperState(long value) { mValue = value; }
protected SuperState(SuperState last) { mValue = last.mValue + 1; }
...
public static class FirstState {
//Can call SuperState(long) from here
}
}
If this doesn't seem appropriate to you, then probably you should leave both constructors open.
If, as it seems to me, you're making a chain-like structure, then you probably don't even want to have FirstState as an accessible class:
public abstract class SuperState {
public final long mValue;
private SuperState(long value) { mValue = value; }
protected SuperState(SuperState last) { mValue = last.mValue + 1; }
...
private static class FirstState extends SuperState {
private FirstState() { super(0); }
}
public static SuperState getFirstState() { return new FirstState(); }
}
One way I can think of, though I find it ugly :
protected SuperState(long value)
{
if (!this.getClass().getName().equals("SomeConcreteClassName"))
throw new SomeException ();
mValue = value;
}
Though Tom's comment about putting the FirstState class in the same package as SuperState and using package private access sounds better.
I think the only way to achieve it is to use analog of "friend". The trick is to have private Value class in the FirstState which is possible to construct only by FirstState. Other classes can see the FirstState.Value class, but cannot instantiate it.
abstract class SuperState {
public final long mValue;
protected SuperState(FirstState.Value value) { mValue = value.value; }
protected SuperState(SuperState last) { mValue = last.mValue + 1; }
}
class FirstState extends SuperState {
public static class Value { private Value() {} }
private static Value value = new Value();
public FirstState() { super(value); }
}
class SecondState extends SuperState {
public SecondState(SuperState last) { super(last); }
}
You can do it with default access modifier like this:
package a;
public abstract class SuperState {
public final long mValue;
SuperState(long value) { mValue = value; } // constructor has default access modifier
protected SuperState(SuperState last) { mValue = last.mValue + 1; }
...
}
package a;
public class FirstState extends SuperState {
public FirstState() { super(0); }
...
}
package b;
// is not able to access constructor SuperState(long) ie. calling contructor
// SuperState(long) will result in compile time error
public class SecondState extends SuperState {
public SecondState(SuperState last) { super(last); }
...
}
Im quite new to Java and this might be a basic doubt. But please help.
I have a class as below:
public class EnterLeaveHandler implements IOtfHandler {
public void handle(java.lang.Object ... args) {
long time = (Long) args[0];
int func = (Integer) args[1];
int cpuid = (Integer) args[2];
int source = (Integer) args[3];
}
I have another class:
public class DefFunctionHandler implements IOtfHandler {
public void handle(Object... args) {
int stream = (Integer) args[0];
int func = (Integer) args[1];
String name = (String) args[2];
int funcgroup = (Integer) args[3];
int source = (Integer) args[4];
}
}
So like you can see..there are 2 different classes, which have the same method, but receive different data. I need to get an input from the user for the "String name" in DefFunctionHandler class, and I identify the given name with the name in the file that I have...then correlate it with other data in the method like funcgroup and func. The same func is there in the other class too. So I need to make a comparison between them to get the data in the other class like time, etc.
So the data in the methods can be compared to the data structure in C...how do I implement such a structure in Java? I read that structs are similar to classes in Java. But in my case, I have the data in methods and not classes. Please tell me how to solve this problem.
To Answer Your Original Question
Long story short, you can't access method variables externally. What you want to do is make those variables fields within the class. Putting them outside the method means they stick around after the method is done, and it means you can access them from outside.
public class EnterLeaveHandler implements IOtfHandler {
private long time;
private int func;
private int cpuid;
private int source;
// Please don't use varargs like this; read the whole answer!!
public void handle(Object ... args) {
time = (Long) args[0];
func = (Integer) args[1];
cpuid = (Integer) args[2];
source = (Integer) args[3];
}
}
Then you access them by creating getters and setters:
public long getTime() {
return time;
}
public void setTime(long t) {
time = t;
}
// etc...
HOWEVER, Some Suggestions...
Your code is... strange, to say the least. It's also very non-Java-like. As much as possible, you should try to avoid having multiple overriding methods that need different data. Also, you normally want to initialize your fields in the constructor, not in some other method.
It's not clear how much of the code you have access to, but if you're able to rewrite the interface, I would definitely do so. Object varargs in an interface is just weird. The reason for using an interface is so that you can call an interface method with identical parameters and, regardless of the object type underneath, something useful will happen. It defeats the point of the interface to have two implementations of the same method require totally different arguments. The following code demonstrates why this is:
IOtfHandler h1 = new EnterLeaveHandler();
IOtfHandler h2 = new DefFunctionHandler();
h1.handle(0, 0, 0, 0);
h2.handle(0, 0, 0, 0); // Crashes with ClassCastException!! :(
// And would also crash two lines later with ArrayIndexOutOfBoundsException
Much better to just make them different methods entirely.You know what variables you're expecting, so you should take advantage of that fact. Your method signatures would be far better off looking something like this:
public class EnterLeaveHandler implements IOtfHandler {
public void handle(long time, int func, int cpuid, int source) {
// Do things with your shiny new variables
}
public class DefFunctionHandler implements IOtfHandler {
public void handle(int stream, int func, String name, int funcgroup, int source) {
// Do things with your shiny new variables
}
}
As others have suggested, if the "real" method signatures are not identical, you shouldn't be using an interface. Better to use an abstract base class instead, to hold what little data is common between them:
abstract class IOtfHandler {
private int source;
private int func;
public void setSource(int source) {
this.source = source;
}
// etc
}
class EnterLeaverHandler extends IOtfHandler {
private long time;
// etc
}
class DefFunctionHandler extends IOtfHandler {
private String name;
// etc
}
Of course, if you set all the variables in the constructors, you may be able to add an abstract handle() method to the base class, since then that method should have the same signature, and take no arguments at all!
Final Result
So if we pull together all the changes I've talked about-- moving the method variables into fields, using getters and setters, using useful method signatures, using constructors, and using a base class instead of a misleading interface, we end up with something like this:
abstract class IOtfHandler {
private int source;
private int func;
public void setSource(int source) {
this.source = source;
}
public int getSource() {
return source;
}
public void setFunc(int func) {
this.func = func;
}
public int getFunc() {
return func;
}
// abstract handle method
abstract public void handle();
}
class EnterLeaverHandler extends IOtfHandler {
private long time;
private int cpuid;
// getters and setters
public void setTime(long time) {
this.time = time;
}
public long getTime() {
return time;
}
public void setCpuId(int cpuid) {
this.cpuid = cpuid;
}
public int getCpuId() {
return cpuid;
}
// constructor
public EnterLeaverHandler(long time, int cpuid, int source, int func) {
setTime(time);
setCpuId(cpuid);
setSource(source);
setFunc(func);
}
// handle method
public void handle() {
System.out.println("EnterLeaverHandler.handle()");
// Do whatever class-specific handling you might want to do in here.
}
}
class DefFunctionHandler extends IOtfHandler {
private String name;
private int funcGroup;
private int stream;
// getters and setters
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setFuncGroup(int funcGroup) {
this.funcGroup = funcGroup;
}
public int getFuncGroup() {
return funcGroup;
}
public void setStream(int stream) {
this.stream = stream;
}
public int getStream() {
return stream;
}
// constructor
public DefFunctionHandler(String name, int funcGroup, int stream, int source, int func) {
setName(name);
setFuncGroup(funcGroup);
setStream(stream);
setSource(source);
setFunc(func);
}
// handle method
public void handle() {
System.out.println("DefFunctionHandler.handle()");
// Do whatever class-specific handling you might want to do in here.
}
}
public class Main {
public static void main(String[] args) {
IOtfHandler h1 = new DefFunctionHandler("name", 0, 0, 0, 0);
IOtfHandler h2 = new EnterLeaverHandler(0, 0, 0, 0);
h1.handle();
h2.handle();
}
}
In order to make the variables class variables, all you have to do is move their declaration outside of the method. In other words, your code for the EnterLeaveHandler might look like this:
public class EnterLeaveHandler implements IOtfHandler {
long time;
int func;
int cpuid;
int source;
public void handle(java.lang.Object ... args) {
time = (Long) args[0];
func = (Integer) args[1];
cpuid = (Integer) args[2];
source = (Integer) args[3];
...
}
}
Create an abstract super class for your classes. Extend this with your classes and init the parameters in the handle call.
public abstract class AbstarctFunctionHandler implements IOtfHandler {
long time;
int func;
int cpuid;
int source
//add getters and setters, if you fancy
public boolean equals(AbstarctFunctionHandler obj){
//compare variables
return true;
}
}
You need to restructure your objects to have proper constuctors and setters/getters
This gives the benefit of protecting all your private variables and forcing other classes to adhere to your classe's "contract" by only allowing them to access it's inner variables via those setters/getters and constructor. Now you just instantiate the object, then use ti's methods to manipulate it.
Here is an example from your first example class:
public class EnterLeaveHandler implements IOtfHandler {
private long time;
private int func, cpuid, source;
public EnterLeavehandler(long time, int func, int cpuid, int source) {
this.time = time;
this.func = func;
this.cpuid = cpuid;
this.source = souce;
}
public long getTime() {
return this.time;
}
public void setTime(long time) {
this.time = time;
}
public int getFunc() {
return this.func;
}
public void setFunc(int func) {
this.func = func;
}
public int getCPUID() {
return this.cpuid;
}
public void setCPUID(int cpuid) {
this.cpuid = cpuid;
}
public int getSource() {
return this.source;
}
public void setSource(int source) {
this.source = source;
}
public void handle(long t, int f, int c, int s) {
this.setTime(t);
this.setFunc(f);
this.setCPUID(c);
this.setSource(s);
}
}
The best solution I could think of
1. is create a getter and setter
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
http://docs.oracle.com/javaee/6/tutorial/doc/gjbbp.html
2.create a wrapper method to do the comparsion prior to calling the individual method.
Hope this helps you.