Polymorphism example? (Substitution principle and late dynamic binding) - java

Below is a snippet of my code and I can’t decide whether or not it is an example of Polymorphism.
Class hierarchy 1
Within my Player class (This is a subclass of Character) there is a method called showStats().
public String showStats(){ // Displays all current stats regarding the player.
String stats = "<html><br>Name: "+ getName()+ "<br>Type: "+ getCharacterType() + "<br>Health: "+ getHealth() +"<br>Weapon Equipped: "+ getWeaponEquippedName()+"<br>Miles Walked: "+getWalked()+"<br>"+showInventory()+"<br>Level Completed: "+getLevelCompleted();
return stats;
}
This method is overridden within the Magician and Warrior classes due to exclusive statistics only Warriors and Magicians would possess if they are of that type (Warriors have a power points attribute and Magicians have a steal points attribute).
Magician Class:
public String showStats(){ // Overridden method that shows all player stats including the number of steal points.
String stats = super.showStats()+"<br>Steal Points: "+getMana()+"</html>";
return stats; }
Warrior Class:
public String showStats(){ // Overridden method that shows all player stats including the number of Power Points if they are a Warrior.
String stats = super.showStats()+"<br>Power Points: "+getMana()+"</html>";
return stats;
}
Within the class Battle I call the showStats() method and the output is not known until the User has selected what character they wish to play as. I just wanted to be certain that this is an example of polymorphism as the character selected is not known until the program has already been compiled and is then selected by the user (i.e. Substitution principle and Late Dynamic Binding).
public static void gameMenu(Player player, int choice, String name)throws FileNotFoundException, IOException, ClassNotFoundException { // Game menu method is for displaying all options (Play game, view game rules, quit) to the user when the game runs.
//Substitution principle applied to the player object depending upon what character the player wishes to select.
if (choice == 3) {
player = new Attack_Warrior();
}
else if (choice == 4) {
player = new Defensive_Warrior();
}
else if (choice == 5) {
player = new Attack_Magician();
}
else if (choice == 6) {
player = new Defensive_Magician();
}
else{
System.out.println("Error. Try again.");
play(player); // If the user enters an invalid input, the method loops and asks the player to re-enter their input.
}
Thank you very much for your time and I look forward to hearing your response,
Alex

It is helpful to annotate the method of your child classes with #Override. If you do not get a compilation error, any code written with the parent type is a proper polymorphic call ;-)

Related

Accessing an object of a class from another class object

Starting of I want to apologise for my english as I'm not a native speaker. The title might be a bit off since I was not sure how to phrase it but hopefully it will come through once I show my code.
The problem I'm phasing is I want to use the shop class to handle any purchases while storing the money variable on the player class.
Is there any way to access the money integer of the player class without creating an object of the player class in the shop class ?
I was thinking about using a static integer to store the data in but from what I've read online its bad practice to use static datatypes.
public class Beta {
public static void main(String[] args) {
Player p1 = new Player("Test");
Shop s1 = new Shop();
p1.setMoney(100);
s1.clerk(p1.getMoney());
}
}
public class Player {
private int money;
private String name;
public Player(String name) {
this.name = name;
}
public int getMoney() {
return money;
}
public void setMoney(int x) {
this.money +=x;
}
}
public class Shop {
private int money;
public void clerk(int x) {
this.money = x;
if (this.money >= total) {
question4 = false;
System.out.println("Your purchase was successful!");
if (blue > 0) {
this.addInventory("Blue", blue);
}
if (red > 0) {
this.addInventory("Red", red);
}
if (green > 0) {
this.addInventory("Green", green);
}
}
else {
question4 = false;
System.out.println("Sorry you cant afford that!");
}
}
}
}
So I cut down my code to show you only the essential parts.
What I want to do is access p1:s money variable from the player class from within the Shop class.
So far I have been passing the variable when calling it from main. Is this the only option I have or can it be accessed in any other way ?
Any help would be much appreciated!
I believe the option that follows Object-Oriented Programming principles best is to pass the actual Player in as an argument, instead of just the money.
Basically, passing just the player's money in instead of the player themselves is like just handing your wallet over to the cashier. You wouldn't do that, right?
This way, the clerk can ask the customer if they have enough money by calling player.getMoney(), and the customer can tell them the answer.
After making the purchase, the player can remove the money from their wallet themselves when the clerk asks them to via player.setMoney().
Now, you asked in a comment about "passing the actual player as an argument without creating a new object of the player class." Java passes arguments by value, and all objects' values are simply the address that hold the information for that particular instance.
So for Player p1 in Beta, let's pretend all of p1's information is stored in a block starting at...let's say, address 21343. In this case, the variable p1 only contains that single number, 21343.
Since Java passes by value, then when you call s1.clerk(Player player), the player variable will also contain 21343. Since it's editing the items contained at the same address, you've essentially passed on p1 itself instead of creating a new Player. In short, the clerk and the main method work with the same object.
The fact that Java passes by value is also why passing just the player's money in doesn't adjust it automatically: The money is an int rather than an object. Since it's an int, when you pass it to the clerk, you're just saying "Hey, clerk, this is the amount of money being worked with." But the clerk has no idea who the money belongs to, so while it can take money, or even give it some, it's essentially just setting it down on the counter, and it's the responsibility of the player to pick it up from there when they're done. By passing in the player instead, the clerk knows who the money belongs to because it's actually asking the player how much money they have.
Another potential solution would be to make p1 and s1 static variables in the Beta class. It'd look something like this:
public class Player
{
public static Player p1;
public static Shop s1;
public static void main(String[] args)
{
p1 = new Player("Test");
s1 = new Shop();
p1.setMoney(100);
s1.clerk(p1.getMoney());
}
}
From there, you'd import the Beta class in Shop, then call Beta.p1 in Shop to access p1.
Hope this helps!

how to use method on specific object from arraylist

EDIT2: Sorry all... I believe it is due to the lack of understanding of question that cause this misconception. After reading through, I think what they want is for the return value of getWinningPoint() be the biggest number among the players and yet still <=21. so that in the game output, can loop each player to get their card point again and compare it to this winningpoint. I thank all of your input and help. Moderator or Admin can close this thread. Thanks again.
I would like to find out how to access the particular object in the arraylist so that i can cast the method on it. In a overall view, I am able to make method that apply to all items in the arraylist of players (distributeCardsToPlayer). But my 2nd method of getWinningPoints() is a int that sum up all the cards the particular player in arraylist players have. The winningPoint is a individual result which will ultimately be used in printWinners() method. I'm only familiar with accessing a obj with "Player player = players.get(0);" but in this case the "player" itself will be calling getWinningPoints() to check their own result.
P.S - I am not sure how to put it properly,and hopefully someone can point me to the right direction.
import java.util.*;
public class ModifiedBlackJack
{
protected ArrayList<Card> gameDeck;
protected ArrayList<Player> players;
public ModifiedBlackJack(ArrayList<Player> players)
{
this.players=players;
}
public void distributeCardsToPlayers()
{
Scanner console = new Scanner(System.in);
for (Player player : players)
{
player.drawACard(getACardFromDeck());
player.drawACard(getACardFromDeck());
System.out.println(player.getName()+": " + player.toString());
System.out.print("Draw another card? (y/n): ");
char input = console.nextLine().toLowerCase().charAt(0);
if(input == 'y')
{
player.drawACard(getACardFromDeck());
}
}
EDIT2: After reading through, I think what they want is for the return value of getWinningPoint() be the biggest number among the players and yet still <=21. so that in the game output, can loop each player to get their card point again and compare it to this winningpoint.
public int getWinningPoints()
{
int wp=0;;
int point=0;
for (Player player:players)
{
point = player.getCardsPoints();
if (point>=21 && point>wp)
{
wp=point;
}
}
return wp;
}
In the Player class, there is a function for summing up all the cards point
public int getCardsPoints()
{
int point=0;
for (Card c: cards)
{
point=point+c.getPoints();
}
return point;
}
I am new to java and any help or guidance is very much appreciated.
Thank You
You may be overthinking this, and the method getWinningPoints isn't entirely required.
Because you already have getCardsPoints declared in Player, and you already have an instance of Player to work with in your loop, the only thing you realistically need to do is...invoke it.
System.out.println(player.getName() + "Chips: " + player.getChips() + "[]" + player.getCardsPoints());
Whatever conditions you need to satisfy the min parameter should be done inside of this loop; that is, conditionally print the values that are larger than min.
If you want to invoke a Player class method you need to have a player object to call a method that it "owns".
Pass the player object to the method and accept the player object in getWinningPoints().
Call
getWinningPoints(player)
Declaration
public int getWinningPoints(Player localPlayer)
{
return localPlayer.getCardsPoints();
}

Library System: Borrowing

I do not know how to do the borrowHolding() in the Library Menu I have to create.
So the purpose of the borrowHolding() is for members to be able to borrow books or videos.
This is a just a sample data of the array:
member[0] = new StandardMember("ID", "Name");
member[1] = new PremiumMember("ID", "Name");
holding[0] = new Book("ID", "Title");
holding[1] = new Video("ID", "Title", loanFee);
This is the borrowHolding() method in the TestLibrary class: (the array is in the TestLibrary class too)
public static void borrowHolding(){
String option;
option = input.next();
do{
Scanner scan = new Scanner(System.in);
int tempId = 0;
System.out.println("Enter your ID: ");
String searchID = scan.next();
for(int i = 0; i < member.length; i++){
if(member[i].getID().equals(searchID)){
tempId = i;
}
}
So for the method, I tried to write a code that will search through the array to find the memberID that wants to borrow. It is not completed yet because I believe I am not doing it correctly
There is a Member class that contains
public class Member{
public Holding[] getCurrentHoldings(){
}
}
from the name of the method, it is used to store the holdings of the members that borrowed. So if member 1 borrows a book, that book will be stored inside the array, i think. I was thinking of using an ArrayList for this method, but not sure if it would make sense.
To borrow a book or video, there are certain conditions to be able to borrow, but I do not know how to implement this into the borrowHolding(). One of the condition are in the Holding class.
public class Holding{
public boolean borrowHolding(){
if(status == true && isOnLoan() == false)
borrowDate = newDateTime(); //this is to get the time when the book or video is borrowed
return true;
}else
return false;
}
}
And there is another condition in the Member class is that the Member must have enough credit to borrow. A book loan fee will cost $10 and a video will vary from $4 or $6.
I think I wrote a few information that is not needed but I guess its better than less information.
My problem is what do I do to the borrowHolding() method in the LibraryMenu? how do I make that if a member wants to borrow a holding, the holding will go under the member's array in the member class
public class Member{
public Holding[] getCurrentHoldings(){
}
}
with the condition from the holding class if it is met, and while executing the borrowHolding method, the method from the member class will be able to subtract the member credit by the loan fee from the book or video. is it possible?
public class Member{
private int credit = 30;
public int calculateRemainingCredit(){
credit = credit - //(the loan fee from the book or video class)
}
}
If your intentions are to add a holding to the member class then this is possible. I would suggest adding an ArrayList of Holding's rather than a regular array because it seems as if the size is going to be constantly changing.
public class Member{
private ArrayList<Holding> currentholdings; // you may need to import the arraylist
private int credit;
public void init(){ // goes in constructor
currentholdings = new ArrayList<Holding>();
credit=0;
}
public void addHolding(Holding newholding){ // adds a new holding to the members array
currentholdings.add(newholding);
credit-=newholding.getFee(); // will need to add a fee variable to the holding class;
}
}
And as for checking to see whether or not the member has enough "credit", that can be done in the borrowHolding() method right after you identify the index of the array. I would just recommend adding a parameter of the member to the borrowHolding() method so you can easily access the variables from that member.
if(member[i].getID().equals(searchID)){
tempId = i;
int tempHolding; // index of whatever holding you wanted (could get this from the scanner)
if (holding[tempHolding].borrowHolding(member[tempId])){ // check status
member[tempId].addHolding(holding[tempHolding]); // they have passed the req. so you can add the holding
}
break;
}
Hope this answered your question.

How do I make an IF statement that compares 2 integers assigned to 2 string variables in 1 class then execute the code in another class in Java?

I have these 2 string variables, Hulk and Thing, Hulk has a strength of 10 and Thing has a strength of 53, they both fight (the IF statement) where the higher integer strength wins.
Then Hulk received a powerup boosting his strength to 110, now both fight again. The winner's name is printed on the screen both times.
I have 2 classes (a main class and a supporting one). The IF statement of my supporting class is attached along with my getStrength() method (if anymore code is needed let me know).
I am getting an error where is says: if (name1.getStrength() > name2.getStrength()) ; the error is that getStrength() isn't defined for string where name1 and name2 are.
Also, after solving this, how do I call this subroutine in my main class?
Thanks in advance!
IF Statement:
if (name1.getStrength() > name2.getStrength())
{
System.out.println(name1 + " Wins!");
}
else {
System.out.println(name2 + " Wins!");
}
getStrength method:
int getStrength() {
return this.strength;
}
You need to make the characters as objects of class that has properties like name, strength, etc.
Then this thing should work : if (Hulk.getStrength() > Thing.getStrength())
Firstly you should read about java first steps.
But in your app, you should create class which is representing your fighters and in this class create methods which get the strength from it, i.e.:
public class Fighter {
private String name;
private int strenght;
public int getStrength() {
return strength;
}
}
of course you need to create constructor or other setters/getters in this class. Then you can create objects, i.e.:
Fighter hulk = new Fighter();
Fighter thing = new Fighter();
// use constructor or setters to set strength and name
Now you can call method from class Fighter:
if(hulk.getStrength() > thing.getStrength()) {
// your code
}
Your error is because you were trying to call getStrength() method on object of String type. The best way is to create your own type.

Manipulating Variables using Setters and Getters

I came across this code example on another website. I've been looking at it for a while, trying to figure out something simple, but I'm having difficulty determining where to start.
How would I allow a user to enter into the console to turn the light or the fan on/off?
All this stuff with setters/getters is confusing. Writing the logic of turning something on/off seems simple, but mix it in with constructors and setters/getters and I get lost. I'm failing to understand how and where to manipulate the isOn boolean with user input.
I'd appreciate any guidance or code.
Thanks
public class Household {
public String choice;//instance variables
public boolean isOn;
//constructor
Household(String choice,boolean isOn) {
this.isOn=isOn;
this.choice=choice;
}
//methods
public String getChoice() {
return choice;
}
public void setChoice(String choice) {
this.choice = choice;
}
public boolean isOn() {
return isOn;
}
public void setOn(boolean isOn) {
this.isOn = isOn;
}
public String toString() {
return "Choice:" + getChoice() + "\tisOn:" + (isOn() ? "Yes" : "NO");
}
public static void main(String[] args) {
Household hh=new Household("toaster", true);
System.out.println(hh);
hh=new Household("fan", false);
System.out.println(hh);
}
}
You can think of a constructor as like a blueprint.
In the above picture, we have the class in the dotted box. This is the "blueprint." It's not an actual object yet, it just represents how objects should look. In the solid box is an actual object.
The constructor takes the blueprint and actually builds something from it.
Household(String choice,boolean isOn) {
this.isOn=isOn;
this.choice=choice;
}
Here, we're defining how that blueprint works. In order to build a household object, we need to supply it with a string "choice" and a boolean "isOn".
Once we have those two things, we can create a Household object.
Now, you can't turn on the lights in your house before they're built.
Once you have a Household object, you'll also have your choice and isOn fields.
Say I want to turn off whatever is in the house.
Using your code, we have a household named hh, a toaster, and an on/off switch. If you wanted to turn off the on/off switch, you'd use the setter:
public void setOn(boolean isOn) {
this.isOn = isOn;
}
The setter then sets the value of the isOn field on the hh object, as seen in the above picture.
If you wanted to know whether that switch was true or false (on or off), you'd ask:
hh.getOn();
This returns a boolean value, the same value as the isOn field on the object.
You can see this when you call
System.out.println(hh.getOn());
This prints out true or false, depending on whether or not it's set to true or false.
That's how setters and getters work: the setter sets the value of that field, and the getter gets the value of the field.
Now for the (more) fun part.
Since you want to input data, rather than simply outputting data, we have to do something different.
Say I want to have a user type into the console "off" and have it set the households on/off switch to off.
System.out.println(hh); <-- only prints out to console
We need a new object to handle input. Scanner is commonly used for teaching beginners, so we'll use that.
Scanner s = new Scanner(System.in);
This reads data from the system's input stream. You can read about Scanner here.
Now, scanner reads data in as a string using nextLine();
So we'll use that.
String test = s.nextLine();
And of course now we need to test if that string is the same as "off", and if it is, set the isOn field to false (off).
if(test.equals("off") || test.equals("OFF")){
hh.setOn(false);
}
I won't go into more details on how to do the rest of this, such as checking input, looping, etc.
The logic should be in the main method in this application.
Wherever you need to modify the household object is where you need to call those setter/getter methods. The constructor is only ever called when you need a brand new object. If this is still confusing, compare the constructor to setting up a game of monopoly. You initially set up the monopoly board, give everyone their money and starting properties, etc. This is all done so that you can actually play the game. When you lose a property in the game, you would use a setter to remove that property. When you need to see how much money, you'd use a getter.
MonopolyPlayer{
int cash;
MonopolyPlayer(){
cash = 1500;
//we're setting this player up to play the game
}
setCash(int i); //now the player has a new amount of cash
getCash(); // he's checking his account
....etc.
}
And so on.
So to try and break it down.
The idea behind getters and setters is to be able to retrieve and set data on variables inside an object, without having to expose the variables themselves. This means that the fields you have at the top of your class should be declared private. You only want to be able to access them through getters and setters.
In your main method you create an instance of the Household object by using the constructor (you can think of the constructor as the thing which constructs the instance). Your constructor says that to call it, it needs two pieces of data, a String and a boolean. When the constructor is called with these two pieces of data it then stores them in the instance it creates in the fields choice and isOn.
Now that you have your instance of Household (hh), you have an object which contains two pieces of data. If you want to retrieve the data you have stored for one of the variables, you use the getter.
hh.getChoice();
or
hh.isOn();
This will return you the data stored in the choice/isOn field for that specific instance of Household.
If you want to change the data you have stored in hh, you use the setters. So to change the value if isOn you would use
hh.setOn(true);
or
hh.setOn(false);
How would I allow a user to enter into the console to turn the light or the fan on/off?
Using your code, you could do something like this.
public static void main(String[] args) {
System.out.println("Enter On or Off for fan: ");
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
boolean on = false;
if(input.equalsIgnoreCase("yes")) {
on = true;
} else if( input.equalsIgnoreCase("no")) {
on = false;
} else {
System.out.println("Please enter yes or no!");
return;
}
Household fan=new Household("fan", on);
System.out.println(hh);
}
But this isn't really using your setters or getters. You could create your household class like this,
public class Household {
private String choice;//instance variables
private boolean isOn;
public void setOn(boolean isOn) {
this.isOn = isOn;
}
public boolean getOn() {
return isOn;
}
public void setChoice(String choice) {
this.choice = choice;
}
public String getChoice() {
return choice;
}
public String toString() {
return "Choice:" + getChoice() + "\tisOn:" + (isOn() ? "Yes" : "NO");
}
}
And in my code above switch it to:
Household fan = new Household();
fan.setChoice("fan");
fan.setOn(on);
System.out.println(fan);

Categories