I've recently started taking an intro java class(I apologize in advance for my lack of knowledge) and I've run into some trouble. I was required to make a program that contains 3 data fields, 2 constructors, and 4 methods.
I'm having a hell of a time trying to put some input into this, where the user would choose from 1 of the 3 data fields I made up for car prices and choose their vehicle. As far as the constructors go, I made a default one but I'm not sure on how to A) implement another constructor and B) how do I involve the input into this and C) where the methods go in that.
I'm thinking of putting the input first but that ruins my constructors?
I realize I asked a lot, but this is an online class without a text, and I'm basically starving for knowledge. I've included what I got so far below. Feedback is appreciated. Again, I apologize for the lack of knowledge but I'm trying --
public class Vehicle{
int truck;
int car;
int van;
public Vehicle(int t, int c, int v){
truck=t;
car=c;
van=v;
}
public Vehicle(){
truck=0;
car=0;
van=0;
}
}
public static void main (String[] args) {
Vehicle cost= new vehicle(25000,15000,22500);
//*cost.truck=25000; cost.car=15000; cost.van=22500;*//
Vehicle this Vehicle= new vehicle();
Vehicle choice Vehicle= new vehicle(25000,22500);
system.out.println("Default prices are 25000 for a truck, 15000 for a car, and"
+ "22500 for a van, you chose" +
}
}
Based from your question, you must be asking all about how to define classes and use them in general.
Question A. How to implement another constructor?
From your case, I see that you've already define your own constructor, but having problem to define another. To define another constructor, you have to know your parameters that
would be passed.
Here, you have three arguments. (variable t, c, v).
public Vehicle(int t, int c, int v){
truck=t;
car=c;
van=v;
}
Another, constructor with no arguments.
public Vehicle(){
truck=0;
car=0;
van=0;
}
When you define another constructor, you must not define another three arguments constructor of the same type, or another constructor with no arguments.
Therefore, you can have constructor method like this.
public Vehicle(int veh, int price){
switch (veh) {
case 0:
truck = price;
case ...
}
}
Question B. How do I involve the input? Where to involve them in methods
From your problem, this statement is already calling constructor, Which means, you are already involving an input to a class.
Vehicle cost = new Vehicle(25000,15000,22500);
Which is the same as calling a constructor with no arguments, and setting the current prices for the vehicles.
Vehicle choice = new Vehicle();
choice.truck = 25000;
choice.car = 22500;
Now, if you are thinking of is there another way to input datas through methods. It is called Encapsulation. To achieve this OOP concept, you should define data members as Private.
private int truck;
// public int truck; <- not like this.
Then, you can have involve input and probably output. Using the concept of getters and setters. In which you involve methods.
// simple setter
public void setTruckPrice(int t) {
truck = t;
}
// simple getter
public int getTruckPrice(int t) {
return truck;
}
P.S. i forgot to edit its encapsulation.
If you want more information, just refer to these links.
http://docs.oracle.com/javase/tutorial/java/javaOO/classes.html
http://www.tutorialspoint.com/java/index.htm
Related
This is probably a really silly question, but I figured I'd try asking! Basically the question is this: can I use a switch statement in my setters?
Here's what I'm doing: I've created a Monster class with the attributes of healthPoints, description, damage, and type, in which type is an enum. In my driver, I've written a few lines of code that will randomly generate a monster type from the enum values, and it will create a new monster using that type.
The issue is that when I display the monster stats, it shows healthPoints and damage as 0, and description as null. When I try to run the program using the default Monster constructor, it crashes and shows a NullPointerException error.
I think the error is in either my setters or the constructors. Each of the setters has a switch case inside, which sets a certain number of healthPoints, damage, and a specific description depending on the type of monster that is randomly generated. I'm not sure if it's even okay to use a switch statement in a setter because I've never really had to before.
Here is some of my code. First, my constructors.
public Monster(int healthPoints, monsterType type, int damage, String description)
{
setHealthPoints(healthPoints);
setType(type);
setDamage(damage);
setDescription(description);
}
public Monster(monsterType type)
{
setType(type);
}
Below is one of the setters.
public void setHealthPoints(int healthPoints)
{
switch(type)
{
case DROW:
healthPoints = 30;
break;
case LICH:
healthPoints = 40;
break;
case ORC:
healthPoints = 20;
break;
case OWLBEAR:
healthPoints = 20;
break;
case RUST_MONSTER:
healthPoints = 10;
break;
}
this.healthPoints = healthPoints;
}
And below is the line in the driver that creates the monster.
int number = new Random().nextInt(monsterType.values().length);
Monster monster = new Monster(monsterType.values ()[number]);
I want the monster's healthPoints, damage, and description to be set depending on the type of monster that is generated. I'm not sure if this can be done using switches in the setters, and I feel like my mistake is probably obvious and I'm just not seeing it because I've been staring at it for a long time...or, if there's a different or easier way to do this, please let me know! Thank you for taking the time to read; I tried to make my question/problems thorough.
Explanation
Yes you can use switch cases in the constructor and in methods. The issue is that you are calling setHealthPoints before setType but the first methods uses the type in its switch statement:
setHealthPoints(healthPoints);
setType(type);
Therefore the variable type is uninitialized when you visit the switch of setHealthPoints and thus currently null.
A switch statement will throw a NullPointerException if its argument is null. Thus you get the NPE.
You can fix this by first executing setType.
Advice on game architecture
You should create a more readable structure that is also easier to maintain and especially easy to extend.
Therefore consider creating a Monster interface or abstract class. After that create explicit monsters as subclasses. The class Monster will contain everything that is equal among all monsters, try to abstract from specific monsters. The monsters themselve will then only contain what differentiates them from the rest.
For example you could use some kind of this:
public abstract class Monster {
private int mHealthPoints;
private int mDamage;
private String mDescription;
public Monster(int healthPoints, int damage, String description) {
this.mHealthPoints = healthPoints;
this.mDamage = damage;
this.mDescription = description;
}
public int getHealthPoints() {
return this.mHealthPoints;
}
public int getDamage() {
return this.mDamage;
}
public String getDescription() {
return this.mDescription;
}
}
And then you have specific monster classes like
public class Orc extends Monster {
private static int HEALTH = 20;
private static int DAMAGE = 10;
private static String DESCRIPTION = "Nasty orc.";
public Orc() {
super(Orc.HEALTH, Orc.DAMAGE, Orc.DESCRIPTION);
}
}
You also don't need that monsterType enum anymore since you can differentiate via monster instanceof Orc. However for a really modular design you shouldn't work on specific classes. Instead use a lot of interfaces that describe properties and abilities.
For example interfaces like:
CanAttack
IsAttackable
HasHealth
CanWalk
CanFly
CanCollide
...
Your game logic then may be built only on those interfaces. For example CanAttack could look like:
public interface CanAttack {
void attack(IsAttackable target);
}
The huge advantage is that you then can easily extend your game. For example by creating monsters with arbitrary combinations of abilities:
public SuperFlyingPig extends Monster implements
CanAttack, HasHealth, CanWalk, CanFly {
...
}
And it magically will work without any additional coding effort since your logic will not care for the specific monster. It will only work on the interfaces.
I know that interfaces in Java are handled by the virtual machine as abstract classes. So, every class in Java, abstract or not has a constructor. Does this mean that interfaces have a constructor too? Because too me on one hand makes sense to have a constructor since they are abstract classes. On the other hand it doesn´t make sense since interfaces don´t have any attributes to initialize.
So how does it actually work?
Interfaces don't have constructors. Their implementations do.
All an interface is:
interface MyInterface{
void addNumber(int amount);
void subtractNumber(int amount);
int getNumber();
}
You don't "run" an interface, and an interface isn't something you create objects out of.
The class that implements your interface does have a constructor though:
class MyNumber implements MyInterface{
private int myNumber;
//Here is your constructor, called when you instantiate it.
myNumber(int number){
myNumber = number;
}
//Now you need to add the methods in your interface
public void addNumber(int number){
myNumber = myNumber + number;
}
public void subractNumber(int number){
myNumber = myNumber - number;
}
public int getNumber(){
return myNumber;
}
}
So no, interfaces do not have constructors. Hope this helps!
Edit: When you create your object, you call your constructor:
MyNumber number = new MyNumber(5); //Calls the constructor and creates a new MyNumber with the value of 5.
number.addNumber(6); //Adds 6 to your number, it is now 11.
number.subtractNumber(3); //Subracts 3 from your number, it is now 8.
number.getNumber(); //returns the value of myNumber inside of your MyNumber object, which is 8.
Edit 2: I want to elaborate a little more on interfaces. You are correct in saying they don't have any attributes to initilize. They have methods to IMPLEMENT. If you have a "move" method in your interface, it can apply to many, many different things. Cars, dogs, boats, planes, sloths and snakes all move, but how do they move? Cars move faster than sloths, so it moves differently. When you create classes for whatever you need to move, you can change that move method and tailor it to the situation you need. That's the point of an interface, flexibility.
I want to create data structures to capture the following ideas:
In a game, I want to have a generic Skill class that captures general information like skill id, cool down time, mana cost, etc.
Then I want to have specific skills that define actual interaction and behaviours. So these would all extend from base class Skill.
Finally, each player will have instances of these specific skills, so I can check each player's skill status, whether a player used it recently, etc.
So I have an abstract superclass Skill that defines some static variables, which all skills have in common, and then for each individual skill that extends Skill, I use a static block to reassign the static variables. So I have the following pattern:
class A {
static int x = 0;
}
class B extends A {
static {
x = 1;
}
}
...
// in a method
A b = new B();
System.out.println(b.x);
The above prints 1, which is exactly the behaviour I want. My only problem is that the system complains about I'm accessing static variable in a non-static way. But of course I can't access it in that way, because I only want to treat the skill as Skill without knowing exactly which subclass it is. So I have to suppress the warning every time I do this, which leads me to think whether there is a better/neater design pattern here.
I have thought about making the variables in question non-static, but because they should be static across all instances of the specific skill, I feel like it should be a static variable...
You should generally avoid such use of global state. If you know for sure that the field x will be shared across all instances of all subtypes of the base class, then the correct place to put such a field is probably somewhere other than the base class. It may be in some other configuration object.
But even with your current configuration, it just does't make sense since any subclass that modifies the static variable will make the variable visible to all classes. If subclass B changes x to 1, then subclass C changes it to 2, the new value would be visible to B as well.
I think that the way you described in the question, every subclass should have its own separate static field. And in the abstract base class, you can define a method to be implemented by each subclass in order to access each field:
abstract class A {
public abstract int getX();
}
class B extends A {
public static int x = 1;
public int getX() {
return x;
}
}
class C extends A {
public static int x = 2;
public int getX() {
return x;
}
}
As already pointed out by some answers and comments, your approach won't work the way you want because every static block changes the static variable for all classes extending A.
Use an interface and instance methods instead:
public interface A {
int getX();
}
-
public class B implements A {
private static final int X = 1;
#Override
public int getX() {
return X;
}
}
-
A myInstance = new B();
System.out.println(myInstance.getX()); // prints "1"
Recently I asked a question about why all my variables in spawned items were being set to the same damage value (Java switch statements outputting the same numbers) and that code wasn't to blame, however after some deep debugging i've found that when an item is spawned it randomises the damage and then for some reason sets that damage to every previously created item of the same type.
I have 'dagger' and 'sword' classes which extend my 'item' class. This is how I set the damage:
case 3: {Sword sword = new Sword(); World[X][Y].treasureName = "sword"; sword.setDamage(4); returnItem = sword; break;}
And this is my item class:
public abstract class Item {
//How much damage is added to the players attack.
static int damage = 0;
static int defence = 0;
public int getDefence() {
return defence;
}
public void setDefence(int defenceValue) {
defence = defenceValue;
}
public int getDamage() {
return damage;
}
public void setDamage(int damageValue) {
damage = damageValue;
}
}
And my sword class:
public class Sword extends Item {
//How much damage is added to the players attack.
static int damage = 0;
static int defence = 0;
public int getDefence() {
return defence;
}
public void setDefence(int defenceValue) {
defence = defenceValue;
}
public int getDamage() {
return damage;
}
public void setDamage(int damageValue) {
damage = damageValue;
}
}
I'm not sure what this problem is called and not sure what to google being fairly new still. I tried to override the item class but that didn't change anything and i've read about inheritance and I don't understand which part is setting every other weapon instance to the same damage. I wanted to remove the methods in the 'Item' class to see if that would fix it, however other code causing errors prevented me to do this when checking and adding together the damage of all the children of 'Item' - this required a cast of (Item) and i'm not sure of what else I can use as a cast.
Here are the referrals to the 'Item' method:
if (((Item) World[k][i].treasure).getDamage() > 9)
{
Without the cast the error is: getDamage() is undefined for the type Object.
and:
//Recalculates the players damage for recently equipped items.
for (int i = 0; i < numItems; i++) {
itemdamage += items[i].getDamage();
System.out.println("You have a " + itemNames[i] + " giving you " + items[i].getDamage() + " extra damage.");
}
What's wrong? I want to understand this so links to helpful information on why, and what i'm doing wrong would be good. Thanks.
static int damage = 0;
Having a static member means that all objects of the class same the same value. If you remove the static keyword, each object will be able to have a different value for damage.
As to the required cast, it seems that World is an array of Object type. Therefore World[k][i] is of Object type, and you can only call methods of the base Object class on it. If you want to call a method defined in the Item class, you must cast the Object to an Item (assuming the runtime type of that Object is an Item).
Your damage and defense variables should not be static. A static variable is tied to the whole class, not to any one instance of the class. As such, when you call setDamage(), even though the method is an instance method, it updates a static variable which is shared by every existing instance.
Remove the static (did you mean to use protected?) and you won't see the "for some reason sets that damage to every previously created item of the same type" behavior anymore.
See What does the 'static' keyword do in a class? for more. Here's the official Java Language Specification on static fields, as well.
You set the variables damage and defence (spelling mistake here - by the way) to be static. Which means that there's only one copy of each variables for the entire class.
Remove the static keyword before the declaration of both variables - and it'll make any new sword instance (object) - carry its own damage and defence.
Heyhey Fluidic,
I'm still fairly new to Java myself, but I think your problem is that your damage variables are set to static (and I would assume the problem would persist across your defence stats as well!)
I had this problem while learning to develop in C++. I would change a value of one of my constructors which referenced a static variable, and all of the instances would change. It's a constant belonging to the class itself, not the object.
So what's happening, is when you change the damage value; all references that use that static damage variable are being changed.
This site gives a bit of an insight on static variables!
http://www.javatpoint.com/static-keyword-in-java
Lemme know if that helps!
Andy
According to the error :
getDamage() is undefined for the type Object
I think you World array, is an array of Object instead of Item
Could you show us how you manage the World array ?
This question already has answers here:
Managing constructors with many parameters in Java
(8 answers)
Closed 6 years ago.
Assume that I have some subclasses that extend a superclass. These subclasses differ by the parameters passed to the superclass. Unfortunately, like the following example, I can end up with "many" parameters. Is there a general method of avoiding this? Are constructors with "many" arguments considered good practice? Would it be better to have getter/setter methods instead of passing every parameter via constructor?
public abstract class SuperClass {
private int a;
private int b;
.
.
private int z;
public SuperClass(int a, int b, ... int z) {
this.a = a;
this.b = b;
.
.
this.z = z;
}
}
public class SubClass1 extends SuperClass {
public SubClass1() {
super(4, 3, ..., 9);
}
}
public class SubClass2 extends SuperClass {
public SubClass2() {
super(1, 7, ..., 2);
}
}
If your subclasses vary only in the parameters passed to the superclass, you might be looking for the Builder Pattern. A builder for the superclass lets you pass in whatever parameters you need without cluttering your constructor, and if you want subclasses for readability, you can just wrap a call to the builder and return its result from the subclass constructors.
Generally, constructors with many parameters is a code smell. It means you probably have a class that breaks the "Single Responsibility Principle". If you can't avoid it, try using the builder pattern!
I would not have constructors in my classes as the behavior of the objects instantiated by each constructor may be different and hard to determine.
One thing to check is: should SuperClass be split into simpler classes?
If this can't be done: if you have too many parameters then you can have a special class that holds the parameters; with setters and getters for each parameter.
One can fill the values in from property files, so you can have profiles for common cases.
class SuperClassParam
{
void seta(int a);
int geta();
//...
}
class SuperClass
{
public SuperClass( SuperClassParam params )
{
}
If the number of parameters can vary, then use a variable arity ("varargs") parameter. Declare an array instead of all those other instance variables. The variable arity parameter is typed as an array when in the method.
private int[] all;
public SuperClass(int... all) {
this.all = all;
}
Your subclass constructors will not have to change at all.