Any tips why my code is taking null as output value instead of the parameter passed on. Kindly please guide me through the code.
Parent Class:
class Language{
protected String name;
protected int numSpeakers;
protected String regionsSpoken;
protected String wordOrder;
public Language(String getName, int getNumSpeakers, String getRegionsSpoken, String getWordOrder){
this.name = getName;
this.numSpeakers = getNumSpeakers;
this.regionsSpoken = getRegionsSpoken;
this.wordOrder = getWordOrder;
}
public void getInfo(){
System.out.println(name+ " is spoken by "+numSpeakers+" people mainly in "+regionsSpoken);
System.out.println("The language follows the word order: "+wordOrder);
}
public static void main(String[] args){
Mayan mayanLanguage = new Mayan("Ki'che'",30000);
mayanLanguage.getInfo();
}
}
Child Class:
class Mayan extends Language {
protected String name;
protected int numSpeakers;
Mayan(String languageName,int speakers ){
super(languageName,speakers,"Central America","verb-object-subject");
}
#Override
public void getInfo() {
System.out.println(name+" is spoken by "+numSpeakers+" people mainly in Central America.");
System.out.println("The language follows the word order: verb-object-subject");
System.out.println("Fun fact: "+name+" is an ergative language.");
}
}
I have looked into the code and tried to resolve it by making changes but nothing seems to work, i am getting stuck into what is the mistake that i am not seeing in the code.
Expected is:
Ki'che' is spoken by 2330000 people mainly in Central America.
The language follows the word order: verb-object-subject
Fun fact: Ki'che' is an ergative language.
Actual is:
null is spoken by 0 people mainly in Central America.
The language follows the word order: verb-object-subject
Fun fact: null is an ergative language.
In Mayan you have the fields
protected String name;
protected int numSpeakers;
Removing these will fix your issue. The reason this issue is happening is because when you define the two lines above, you are hiding the two fields from Language and you would have to access the fields from Language like super.name, super.numSpeakers, etc...
Something like the following is what you are probably after.
public class Mayan extends Language {
private static final String REGION = "Central America";
private static final String WORD_ORDER = "verb-object-subject";
public Mayan(String languageName, int speakers) {
super(languageName, speakers, REGION, WORD_ORDER);
}
#Override
public void getInfo() {
super.getInfo();
System.out.println("Fun fact: " + name + " is an ergative language.");
}
}
As Gavin pointed out, the access modifiers can be restricted. If you are working within a single package for your program, you might end up with something like
Language.java
class Language {
String name;
private int numSpeakers;
private String regionsSpoken;
private String wordOrder;
Language(String getName, int getNumSpeakers, String getRegionsSpoken, String getWordOrder) {
this.name = getName;
this.numSpeakers = getNumSpeakers;
this.regionsSpoken = getRegionsSpoken;
this.wordOrder = getWordOrder;
}
void getInfo() {
System.out.println(name + " is spoken by " + numSpeakers + " people mainly in " + regionsSpoken);
System.out.println("The language follows the word order: " + wordOrder);
}
public static void main(String[] args) {
Mayan mayanLanguage = new Mayan("Ki'che'",30000);
mayanLanguage.getInfo();
}
}
Mayan.java
class Mayan extends Language {
private static final String REGION = "Central America";
private static final String WORD_ORDER = "verb-object-subject";
Mayan(String languageName, int speakers) {
super(languageName, speakers, REGION, WORD_ORDER);
}
#Override
void getInfo() {
super.getInfo();
System.out.println("Fun fact: " + name + " is an ergative language.");
}
}
The pet store program should start with the user being able to choose to adopt a pet or give a pet the to the shop. If the user wants to adopt a pet, they should be able to see either all available pets, unless they say they know what type of pet they want, then show only available pets of that type.
The 4 methods that will need to be created for this program should:
add new pets
get a pet adopted
show pets by type
show pets available for adoption
Object Class: Pets.java
import java.util.*;
public class Pets {
public static void main(String[] args){
private double age; // age of the animal (e.g. for 6 months the age would be .5)
private String petName; // name of the animal
private String aType; // the type of the pet (e.g. "bird", "dog", "cat", "fish", etc)
private int collarID; // id number for the pets
private boolean isAdopted = false; // truth of if the pet has been adopted or not
private String newOwner;
private Date adoptionDate;
public double getAge() {
return age;
}
public void setAge(double age) {
this.age = age;
}
public String getPetName() {
return petName;
}
public void setPetName(String petName) {
this.petName = petName;
}
public String getaType() {
return aType;
}
public void setaType(String aType) {
this.aType = aType;
}
public int getCollarId() {
return collarID;
}
public void setCollarId(int collarId) {
this.collarID = collarId;
}
public boolean isAdoptated() {
return isAdopted;
}
public void setAdoptated(boolean isAdoptated) {
this.isAdopted = isAdoptated;
}
public Date getAdoptionDate() {
return adoptionDate;
}
public void setAdoptionDate(Date adoptionDate) {
this.adoptionDate = adoptionDate;
}
#Override
public String toString() {
return "Pets [age=" + age + ", petName=" + petName + ", aType=" + aType + ", collarId=" + collarID
+ ", isAdoptated=" + isAdopted + ", adoptionDate=" + adoptionDate + "]";
}
}
}
You should define the data fields and methods inside the class, but not inside the main()-method. The main()-method is the entry point of your java application and could be used to create an instance of your Pets class.
e.g.:
public static void main(String[] args) {
Pets pet = new Pets();
}
This code is not compiling for 2 main reasons:
You are specifying access modifiers on variables inside a method (in this case main), which is forbidden;
You are writing methods (e.g. getAge) inside another method (main) and trying to return a variable (e.g. age) that is out of that scope, in fact the variable age is not known inside the getAge method, because it's declared in the main method.
You should move the variable declaration to class level, and then have all methods separated using those variables. I'll give you a sketch, not the complete solution:
import java.util.*;
public class Pets {
/* Insert all variable declarations here */
private double age;
/* Constructor if you need it */
public Pets(/* parameters you think you need */) {
// Set attributes when you declare a new Pets()
}
/* Insert all methods you need here */
public double getAge() {
return this.age;
}
The positioning of the main method - for what I've understoon from your description - should be placed outside this class, in another class where the whole application will start to run. The Pet class should serve only for anything concerning pets (the four methods you will need to implement and all getters/setters for retrieving private class variables).
You’ve happened to put about everything — private fields and public methods — inside you main method. That doesn’t make sense. Everything that is in your main, move it outside, right under the line public class Pets {. That should fix your compiler error.
I work on my first Java project, which is a basic roleplaying game. Now I work on spells, and I need some OOD guidance.
I have Character, which is an abstract class. Character has some subclasses (like mage, fighter, rogue, cleric).
Mage and cleric(as for now, cleric doesn't have mana, but it might change) are both spell-casters.
I also have a Spell class, with some info (like spell name, mana cost etc). MageSpellsList and ClericSpellsList are another classes and both have lists of class Spell. and I also have Effects class(casting a spell should use it).
What would be a good object oriented design for dealing with spells (the solution shouldn't include Effects class, I can deal with that later) ?
Maybe using a "SpellCaster" interface with some methods like castSpell and showSpellbook, so Mage and Cleric will implement the interface? .
Maybe MageSpellsList and ClericSpellsList should be a subclass of Spell ? My goal is to use castSpell("spell name here") and let castSpell do the job, by using a good OOD, rather than writing a specific method for each spell (and without duplicate code between mage and Cleric)
Mage.java:
public class Mage extends Character {
private List<Spell> spellBook;
private int mana;
private int CurrentMana;
public Mage(String name) {
super(name);
setName(name);
setCharacterClass("Mage");
setLevel(1);
setHitDice(4);
setStrength(10);
setConstitution(10);
setDexterity(14);
setIntelligence(16);
setWisdom(14);
setCharisma(10);
setHp((int) (4 + getModifier(getConstitution())));
setCurrentHp(getHp());
setArmorClass(10 + getModifier(getDexterity()));
setBaseAttackBonus(0);
setMana(20 + 2 * getModifier(getIntelligence()));
setCurrentMana(getMana());
spellBook = new ArrayList<Spell>();
}
public int getMana() {
return mana;
}
public int getCurrentMana() {
return CurrentMana;
}
protected void setMana(int mna) {
mana = mna;
}
protected void setCurrentMana(int CurrMana) {
CurrentMana = CurrMana;
}
public void showSpellBook() {
for (Iterator<Spell> iter = spellBook.iterator(); iter.hasNext(); ) {
Spell spell = iter.next();
System.out.println("Spell name: " + spell.getSpellName());
System.out.println("Spell effect: " + spell.getEffect());
}
}
public void addToSpellBook(String spellName) {
Spell newSpell;
newSpell = MageSpellsList.getSpell(spellName);
spellBook.add(newSpell);
System.out.println(newSpell.getSpellName() + " has been added to the spellbook");
}
public void chooseSpells() {
System.out.println();
}
void castSpell(String spellName, Character hero, Character target) {
try {
Spell spell = MageSpellsList.getSpell(spellName);
System.out.println("You casted: " + spellName);
System.out.println("Spell effect: " + spell.getEffect());
} catch (Exception e) {
System.out.println("No such spell");
}
}
}
Spell.java:
public class Spell {
private String name;
private int spellLevel;
private String effect;
private int manaCost;
private int duration;
Spell(String name, int spellLevel, String effect, int manaCost, int duration) {
this.name = name;
this.spellLevel = spellLevel;
this.effect = effect;
this.manaCost = manaCost;
this.duration= duration;
}
String getSpellName() { return name; }
int getSpellLevel() { return spellLevel; }
String getEffect() { return effect; }
int getManaCost() {
return manaCost;
}
int getDuration() { return duration; }
}
MageSpellsList.java:
public class MageSpellsList {
static List<Spell> MageSpellsList = new ArrayList<Spell>();
static {
MageSpellsList.add(new Spell("Magic Missiles", 1, "damage", 2, 0));
MageSpellsList.add(new Spell("Magic Armor", 1, "changeStat", 2, 0));
MageSpellsList.add(new Spell("Scorching Ray ", 2, "damage", 4, 0));
MageSpellsList.add(new Spell("Fireball", 3, "damage", 5,0 ));
MageSpellsList.add(new Spell("Ice Storm", 4, "damage", 8, 0));
}
static void showSpellsOfLevel(int spellLevel) {
try {
for (Iterator<Spell> iter = MageSpellsList.iterator(); iter.hasNext(); ) {
Spell spell = iter.next();
if (spellLevel == spell.getSpellLevel()) {
System.out.println("Spell name: " + spell.getSpellName());
System.out.println("Spell effect: " + spell.getEffect());
}
}
} catch (Exception e){
System.out.println("Epells of level " + spellLevel + " haven't been found in spells-list");
}
}
static Spell getSpell(String spellName) {
try {
for (Iterator<Spell> iter = MageSpellsList.iterator(); iter.hasNext(); ) {
Spell spell = iter.next();
if (spellName.equals(spell.getSpellName())) {
return spell;
}
}
} catch (Exception e){
System.out.println(spellName + " haven't been found in spells-list");
return null;
}
return null;
}
}
Effects.java:
public class Effects {
public void damage(int dice, Character attacker, Character target){
int damage = DiceRoller.roll(dice);
System.out.println(attacker.getName() + " dealt " + damage + " damage to " + target.getName());
target.setCurrentHp(target.getCurrentHp() - damage);
}
public static void damage(int n, int dice, int bonus, Character target) {
int damage = DiceRoller.roll(n,dice,bonus);
System.out.println("You dealt" + damage + "damage to " + target.getName());
target.setCurrentHp(target.getCurrentHp() - damage);
}
public static void heal(int n, int dice, int bonus, Character target) {
int heal = DiceRoller.roll(n,dice,bonus);
if (heal + target.getCurrentHp() >= target.getHp()) {
target.setCurrentHp(target.getHp());
} else {
target.setCurrentHp(target.getCurrentHp() + heal);
}
System.out.println("You healed" + heal + " hit points!");
}
public static void changeStat(String stat, int mod, Character target){
System.out.println(stat + " + " + mod);
switch (stat) {
case "strength":
target.setStrength(target.getStrength() + mod);
break;
case "constitution":
target.setConstitution(target.getConstitution() + mod);
break;
case "dexterity":
target.setDexterity(target.getDexterity() + mod);
break;
case "intelligence":
target.setIntelligence(target.getIntelligence() + mod);
break;
case "wisdom":
target.setWisdom(target.getWisdom() + mod);
break;
case "charisma":
target.setCharisma(target.getCharisma() + mod);
break;
case "armorClass":
target.setArmorClass(target.getArmorClass() + mod);
break;
}
}
}
Preamble
I try to generalise the classes as much as possible, so I do not end up with lots of specific classes that just represent different data, instead of a different structure. Also, I try to separate data structures from game mechanics. In particular, I try to keep the combat mechanics all in one place, instead of splitting them across different classes, and I try not to hard-code any data. In this answer, we will cover the characters, their abilities/spells, the effects of the abilities, and the combat mechanics.
Characters
Consider, for instance, a PlayableCharacter, that represents your characters. This is a standard data class. It provides methods for increasing or decreasing health and mana, and a collection of available abilities.
class PlayableCharacter {
private final int maxHealth;
private int health;
private final int maxResource; // mana, energy and so on
private int resource;
private final Collection<Ability> abilities;
// getters and setters
}
Abilities
Abilities are equally data classes. They represent mana costs, triggered effects, and so on. I often represent this as a normal class, and then read the individual abilities from external data files. Here we can skip that and declare them with enumerations.
enum Ability {
FIREBALL("Fireball", 3, 5, new Effect[] {
new Effect(Mechanic.DAMAGE, 10, 0),
new Effect(Mechanic.BURN, 2, 3)
});
private final String name;
private final int level;
private final int cost;
private final List<Effect> effects;
}
Effects
Finally the effects tell what an ability does. How much damage, how long it lasts, how it affects a character. Again, this is all data, no game logic.
class Effect {
private final Mechanic effect;
private final int value;
private final int duration;
}
The mechanics are just an enumeration.
enum Mechanic {
DAMAGE, BURN;
}
Mechanics
Now it is time to make things work properly. This is the class that your game loop will be interacting with, and you must feed it the game state (which characters are battling, for instance).
class BattleEngine {
void useAbility(PlayableCharacter source, PlayableCharacter target, Ability ability) {
// ...
}
}
How you implement each mechanic is up to you. It can range from an infernal switch or if/else for each Mechanic, or you can move the code to the Mechanic enum, or to private nested classes and use an EnumMap to retrieve each handler.
Example Mechanic
interface MechanicHandler {
void apply(PlayableCharacter source, PlayableCharacter target, Effect effect);
}
class BattleEngine {
private final Map<Mechanic, MechanicHandler> mechanics;
void useAbility(PlayableCharacter source, PlayableCharacter target, Ability ability) {
source.decreaseResource(ability.getCost());
for (Effect effect: ability.getEffects()) {
MechanicHandler mh = mechanics.get(e.getMechanic());
mh.apply(source, target, effect);
}
}
private static final class DicePerLevel implements MechanicHandler {
#Override
public void apply(PlayableCharacter source, PlayableCharacter target, Effect effect) {
int levels = Math.min(effect.getValue(), source.getLevel());
int damage = 0;
for (int i = 0; i < levels; ++i) {
int roll; // roll a d6 die
damage += roll;
}
target.decreaseHealth(damage);
}
}
}
The SpellCaster spellbook should be a Map<String, Spell> so you can look it up by name when it is cast. The Spell class should define an abstract method for applying the effects to a Character. I don't see the point of a "SpellCaster" interface because the implementation of the castSpell() method is always the same (the behavior is delegated to the Spell itself).
Here is a sample scenario:
Mage fireMage = new Mage("Red Niminim");
fireMage.addSpell(new Fireball());
fireMage.addAttribute(Attribute.RESIST_FIRE);
fireMage.addAttribute(Attribute.WEAK_TO_COLD);
Mage iceMage = new Mage("Blue Niminim");
fireMage.addSpell(new Icestorm());
fireMage.addAttribute(Attribute.RESIST_COLD);
fireMage.addAttribute(Attribute.WEAK_TO_FIRE);
Cleric cleric = new Cleric("Friar Joe");
cleric.addSpell(new Heal());
// battle!
fireMage.castSpell("Fireball", cleric); // 15 damage
fireMage.castSpell("Fireball", iceMage); // 30 damage
fireMage.castSpell("Fireball", fireMage); // 0 damage
iceMage.castSpell("Icestorm", cleric); // 15 damage
iceMage.castSpell("Icestorm", fireMage); // 30 damage
iceMage.castSpell("Icestorm", iceMage); // 0 damage
cleric.castSpell("Heal", cleric); // 15 healed
Attribute.java
public enum Attribute {
RESIST_FIRE, WEAK_TO_FIRE, RESIST_COLD, WEAK_TO_COLD;
}
Spell.java
public abstract class Spell {
private String name;
private int manaCost;
public Spell(String name, int manaCost) {
this.name = name;
this.manaCost = manaCost;
}
public abstract void apply(Character character);
public String getName() {
return name;
}
public int getManaCost() {
return manaCost;
}
}
SpellCaster.java (snippet)
public void castSpell(String name, Character character) {
getSpellBook().get(name).apply(character);
}
public void addSpell(Spell spell) {
getSpellBook().put(spell.getName(), spell);
}
Fireball.java
public class Fireball extends Spell {
private static final String NAME = "Fireball";
private static final int MANA_COST = 8;
private static final int DAMAGE_AMOUNT = 15;
public Fireball() {
super(NAME, MANA_COST);
}
#Override
public void apply(Character character) {
int damage = DAMAGE_AMOUNT;
if (character.getAttributes().contains(Attribute.RESIST_FIRE)) {
damage = 0;
}
else if (character.getAttributes().contains(Attribute.WEAK_TO_FIRE)) {
damage = damage * 2;
}
character.setCurrentHp(character.getCurrentHp() - damage);
}
}
Icestorm.java
public class Icestorm extends Spell {
private static final String NAME = "Icestorm";
private static final int MANA_COST = 8;
private static final int DAMAGE_AMOUNT = 15;
public Icestorm() {
super(NAME, MANA_COST);
}
#Override
public void apply(Character character) {
int damage = DAMAGE_AMOUNT;
if (character.getAttributes().contains(Attribute.RESIST_COLD)) {
damage = 0;
}
else if (character.getAttributes().contains(Attribute.WEAK_TO_COLD)) {
damage = damage * 2;
}
character.setCurrentHp(character.getCurrentHp() - damage);
}
}
Heal.java
public class Heal extends Spell {
private static final String NAME = "Heal";
private static final int MANA_COST = 10;
private static final int HEAL_AMOUNT = 15;
public Heal() {
super(NAME, MANA_COST);
}
#Override
public void apply(Character character) {
character.setCurrentHp(character.getCurrentHp() + HEAL_AMOUNT);
}
}
Here is an example of how you can use enum instead of strings in your Effects class. I took the liberty of renaming your Character class to PlayerCharacter to avoid collision with java.lang.Character.
Effects.java:
public class Effects {
...
public static void changeStat(Stat status, int mod, PlayerCharacter target) {
System.out.println(status + " + " + mod);
status.effect(mod).accept(target);
}
}
A little bit cleaner, isn't it? How it works? The magic is all in the enum:
Stat.java:
import java.util.function.Consumer;
import java.util.function.IntUnaryOperator;
import java.util.function.ObjIntConsumer;
import java.util.function.ToIntFunction;
public enum Stat {
STRENGTH(PlayerCharacter::getStrength, PlayerCharacter::setStrength),
CONSTITUTION(PlayerCharacter::getConstitution, PlayerCharacter::setStrength),
DEXTERITY(PlayerCharacter::getDexterity, PlayerCharacter::setDexterity),
INTELLIGENCE(PlayerCharacter::getIntelligence, PlayerCharacter::setIntelligence),
WISDOM(PlayerCharacter::getWisdom, PlayerCharacter::setWisdom),
CHARISMA(PlayerCharacter::getCharisma, PlayerCharacter::setCharisma),
ARMORCLASS(PlayerCharacter::getArmorClass, PlayerCharacter::setArmorClass);
Stat(ToIntFunction<PlayerCharacter> findcurrentvalue, ObjIntConsumer<PlayerCharacter> setnewvalue) {
this.findcurrentvalue = findcurrentvalue;
this.setnewvalue = setnewvalue;
}
private ToIntFunction<PlayerCharacter> findcurrentvalue;
private ObjIntConsumer<PlayerCharacter> setnewvalue;
Consumer<PlayerCharacter> effect(int mod) {
return target -> {
setnewvalue.accept(target, findcurrentvalue.applyAsInt(target) + mod);
};
}
}
The two mysterious types ToIntFunction and ObjIntConsumer are functional interfaces:
ToIntFunction takes some kind of object as input (here: a PlayerCharacter) and returns an int.
ObjIntConsumer takes some kind of object (here: a PlayerCharacter) and an int as input, and returns nothing.
You could also create your own functional interface if you like, like so:
Effect.java:
#FunctionalInterface
public interface Effect<T extends PlayerCharacter> {
void affect(T t);
}
Stat.java:
...
Effect<PlayerCharacter> effect(IntUnaryOperator calculator) {
return target -> {
setnewvalue.accept(target, calculator.applyAsInt(findcurrentvalue.applyAsInt(target)));
};
}
...
Then you can do this in changeStat:
public class Effects {
...
public static void changeStat(Stat status, int mod, PlayerCharacter target) {
System.out.println(status + " + " + mod);
status.effect(x -> x + mod).affect(target);
}
}
This way you can decide in the Effects class what will happen. Well, I don't imagine the character stats to change much from spells, but a similar mechanic can be used for HP and such :)
The x -> x + mod bit could come from the spell itself too. It's a function that takes an int and returns an int, which is called an IntUnaryOperator in Java:
Effects.java:
...
public static void boost(int dice, PlayerCharacter target) {
int value = DiceRoller.roll(dice);
changeStat(Stat.STRENGTH, x -> x + value, target);
}
public static void changeStat(Stat status, IntUnaryOperator change, PlayerCharacter target) {
status.effect(change).affect(target);
}
...
Here the spell (boost in this case, which I just invented!) will increase the player's strength (the STRENGTH constant) by a dice roll. It accomplishes this by calling the changeStat with three parameters:
STRENGTH → tells the method what status to change.
A "formula" for changing the value (note that you don't actually need to know the value here, just the formula!).
The target to affect.
As you can see, there is no need here to know how to find the strength value, or how to set it to something else. That is all handled by the enum, so you can keep your spell code clean.
You could even inline the changeStat method directly in the spell method this way, since there isn't really any "real" code in it anymore – that logic is hidden in the enum.
Clean and neat :)
I think your idea of having a SpellCaster interface (which includes the castSpell()) is a good one. This defines the behavior or ability of the character.
I would include the list of available spells as an instance field in the Mage or Cleric classes. Come to think of it, maybe it would be a good idea to create an abstract class called SpellCaster which extends Character. The SpellCaster class can declare the list of spells and subclasses (Mage and Cleric) can add specific spells to it.
I'm going to discard the Effects class for now. Each spell can take care of its own behavior. So for example, when calling castSpell("spellName", hero, target) you can pass the required parameters to the spell object and it can take care of dealing the damage or changing stats.
In addition, there could be multiple Spell subclasses. For example, DamageSpell, Buff, Debuff. The superclass Spell has a method apply() and each subclass can implement it with it's own behavior. When calling castSpell() then you delegate the control to a specific subclass of a Spell which has encapsulated the behavior and knows exactly if it should deal damage or change stats. That's essentially the Strategy Pattern.
Why treat spells different than abilities? A fighter class might not have spells as magic spells, but it should be able to perform class specific moves like a whirlwind.
Class PlayableCharacter: abstract class, defines the abstract methods for handling resources(regen rate, max, effects on character), abilities, gear. And implements all the basics.
Class ManaCharacter: extends PlayableCharacter handles it resource as mana.
Class Mage extends ManaCharacter: Will just implement the methods to define what kind of gear it can use, the special abilities it can perform, etc.
I'm stuck with a problem here. I want to change the setter from a attribute from the superclass (parent class) in my subclass (child) however when I overide this method in my subclass I can't access my private attributes from the supperclass. And the point is, they have to stay private.
Superclass (problem: setMinimumVoorraad(int voorraad);)
package domein;
public abstract class Artikel implements Weegbaar
{
private String omschrijving;
private double prijs;
private int aantalInStock;
private int minimumVoorraad;
public Artikel(String omschrijving, double prijs, int aantalInStock, int minimumVoorraad)
{
this.setOmschrijving(omschrijving);
this.setPrijs(prijs);
this.setAantalInStock(aantalInStock);
this.setMinimumVoorraad(minimumVoorraad);
}
#Override
public String toString()
{
String output = String.format(" \n omschrijving: %s \n prijs: %f \n In stock %d (minimumvoorraad = %d) \n", this.omschrijving, this.prijs, this.aantalInStock, this.minimumVoorraad);
return output;
}
//----Getters----
public String getOmschrijving() {
return omschrijving;
}
public double getPrijs() {
return prijs;
}
public int getAantalInStock() {
return aantalInStock;
}
public int getMinimumVoorraad() {
return minimumVoorraad;
}
//----Setters----
public void setOmschrijving(String omschrijving) {
this.omschrijving = omschrijving;
}
public void setPrijs(double prijs) {
this.prijs = prijs;
}
public void setAantalInStock(int aantalInStock) {
this.aantalInStock = aantalInStock;
}
public void setMinimumVoorraad(int minimumVoorraad)
{
if(minimumVoorraad < 2)
this.minimumVoorraad = 3;
else
this.minimumVoorraad = minimumVoorraad;
}
}
Subclass
package domein;
public class Food extends Artikel
{
private String houdbaarheidsDatum;
private double nettoGewicht;
public Food(String omschrijving, double prijs, int aantalInStock, int minimumVoorraad, String houdbaarheidsDatum, double nettoGewicht)
{
super(omschrijving, prijs, aantalInStock, minimumVoorraad);
this.setHoudbaarheidsDatum(houdbaarheidsDatum);
this.setNettoGewicht(nettoGewicht);
}
#Override
public boolean isWeegbaar()
{
return true;
}
//----Getters----
public String getHoudbaarheidsDatum() {
return houdbaarheidsDatum;
}
public double getNettoGewicht() {
return nettoGewicht;
}
//----Setters----
public void setHoudbaarheidsDatum(String houdbaarheidsDatum) {
this.houdbaarheidsDatum = houdbaarheidsDatum;
}
public void setNettoGewicht(double nettoGewicht) {
this.nettoGewicht = nettoGewicht;
}
#Override
public void setMinimumVoorraad(int minimumVoorraad)
{
if(minimumVoorraad < 5)
this.minimumVoorraad = 6;
else
this.minimumVoorraad = minimumVoorraad;
}
}
Someone who can help me?
Thanks in advance.
One possibility is to implement the subclass's setter in terms of the superclass's setter (which, presumably, you do have access to).
For example, assuming the setter is setFoo, then the subclass's version might be:
public void setFoo(Foo f) {
// Do subclass stuff pre-setting, if any
super.setFoo(f);
// Do subclass stuff post-setting, if any
}
The answer given above by NPE is absolutely the best way to go about solving this problem. It is elegant and honors basic inheritance contracts between superclass and subclass. Even in your original post, the subclass is actually more restrictive than the superclass, so doing something like:
#Override
public void setMinimumVoorraad(int minimumVoorraad)
{
if(minimumVoorraad <= 5)
super.setMinimumVoorraad(6);
else
super.setMinimumVoorraad(minimumVoorraad);
}
exactly as NPE suggested would probably work. (Note how I modified your if test. Not sure if it's a typo, but in the original implementation 5 would be a valid minimum, but input like 4 would set it to 6.)
Other (possibly acceptable) patterns would be to:
Make the members in your Parent class protected, which would give visibility. (Realize that you did mention a private restriction; this pattern is solely mentioned to provide a more complete overall answer.)
Delegate the validation logic to another method (that is non-private). This way the child can override the validation method.
And now on to the (probably unacceptable) pattern of using Java reflection:
#Override
public void setMinimumVoorraad(int minimumVoorraad) {
try {
Field field = this.getClass().getSuperclass().getDeclaredField("minimumVoorraad");
field.setAccessible(true);
if(minimumVoorraad <= 5)
field.set(this, 6);
else
field.set(this, minimumVoorraad);
field.setAccessible(false);
}
catch(NoSuchFieldException | IllegalAccessException e) {
// do something
}
}
It's worth noting that if you never ever do this in your entire life you will probably be the better for it. Not only does it completely break all contracts, but it relies on hard-coded Strings to do field name lookups, which in and of itself is pretty painful. But it does exist. And no good answer (already given above by NPE) would be complete without an example of how not to do something...
I am a beginner programmer and this is my first question on this forum.
I am writing a simple text adventure game using BlueJ as a compiler, and I am on a Mac. The problem I ran into is that I would like to make my code more self automated, but I cannot call a class with a string. The reason I want call the class and not have it all in an if function is so that I may incorporate more methods.
Here is how it will run currently:
public class textadventure {
public method(String room){
if(room==street){street.enterRoom();}
}
}
public class street{
public enterRoom(){
//do stuff and call other methods
}
}
The if statement tests for every class/room I create. What I would like the code to do is automatically make the string room into a class name that can be called. So it may act like so:
Public method(string room){
Class Room = room;
Room.enterRoom();
}
I have already looked into using Class.forName, but all the examples were too general for me to understand how to use the function. Any help would be greatly appreciated, and if there is any other necessary information (such as more example code) I am happy to provide it.
-Sebastien
Here is the full code:
import java.awt.*;
import javax.swing.*;
public class Player extends JApplet{
public String textOnScreen;
public void start(){
room("street1");
}
public void room(String room){
if(room=="street1"){
textOnScreen=street1.enterRoom();
repaint();
}
if(room=="street2"){
textOnScreen=street2.enterRoom();
repaint();
}
}
public void paint(Graphics g){
g.drawString(textOnScreen,5,15);
}
}
public abstract class street1
{
private static String textToScreen;
public static String enterRoom(){
textToScreen = "You are on a street running from North to South.";
return textToScreen;
}
}
public abstract class street2
{
private static String textToScreen;
public static String enterRoom(){
textToScreen = "You are on another street.";
return textToScreen;
}
}
Seeing as you are rather new to programming, I would recommend starting with some programs that are simpler than a full-fledged adventure game. You still haven't fully grasped some of the fundamentals of the Java syntax. Take, for example, the HelloWorld program:
public class HelloWorld {
public static void main(String[] args) {
String output = "Hello World!"
System.out.println(output);
}
}
Notice that public is lowercased. Public with a capital P is not the same as public.
Also notice that the String class has a capital S.* Again, capitalization matters, so string is not the same as String.
In addition, note that I didn't have to use String string = new String("string"). You can use String string = "string". This syntax runs faster and is easier to read.
When testing for string equality, you need to use String.equals instead of ==. This is because a == b checks for object equality (i.e. a and b occupy the same spot in memory) and stringOne.equals(stringTwo) checks to see if stringOne has the same characters in the same order as stringTwo regardless of where they are in memory.
Now, as for your question, I would recommend using either an Enum or a Map to keep track of which object to use.
For example:
public class Tester {
public enum Location {
ROOM_A("Room A", "You are going into Room A"),
ROOM_B("Room B", "You are going into Room B"),
OUTSIDE("Outside", "You are going outside");
private final String name;
private final String actionText;
private Location(String name, String actionText) {
this.name = name;
this.actionText = actionText;
}
public String getActionText() {
return this.actionText;
}
public String getName() {
return this.name;
}
public static Location findByName(String name) {
name = name.toUpperCase().replaceAll("\\s+", "_");
try {
return Enum.valueOf(Location.class, name);
} catch (IllegalArgumentException e) {
return null;
}
}
}
private Location currentLocation;
public void changeLocation(String locationName) {
Location location = Location.findByName(locationName);
if (location == null) {
System.out.println("Unknown room: " + locationName);
} else if (currentLocation != null && currentLocation.equals(location)) {
System.out.println("Already in room " + location.getName());
} else {
System.out.println(location.getActionText());
currentLocation = location;
}
}
public static void main(String[] args) {
Tester tester = new Tester();
tester.changeLocation("room a");
tester.changeLocation("room b");
tester.changeLocation("room c");
tester.changeLocation("room b");
tester.changeLocation("outside");
}
}
*This is the standard way of formating Java code. Class names are PascalCased while variable names are camelCased.
String className=getClassName();//Get class name from user here
String fnName=getMethodName();//Get function name from user here
Class params[] = {};
Object paramsObj[] = {};
Class thisClass = Class.forName(className);// get the Class
Object inst = thisClass.newInstance();// get an instance
// get the method
Method fn = thisClass.getDeclaredMethod(fnName, params);
// call the method
fn.invoke(inst, paramsObj);
The comments below your question are true - your code is very rough.
Anyway, if you have a method like
public void doSomething(String str) {
if (str.equals("whatever")) {
// do something
}
}
Then call it like
doSomething("whatever");
In Java, many classes have attributes, and you can and will often have multiple instances from the same class.
How would you identify which is which by name?
For example
class Room {
List<Monster> monsters = new ArrayList <Monster> ();
public Room (int monstercount) {
for (int i = 0; i < monstercount; ++i)
monsters.add (new Monster ());
}
// ...
}
Monsters can have attributes, and if one of them is dead, you can identify it more easily if you don't handle everything in Strings.