I have a question about subclasses and superclasses. In a project I'm working on, I have a superclass called "Team" and some subclasses called "TeamBlue","TeamRed"... Also, all of these subclasses have static fields and methods in them.
My question is: how do I store any subclass object (either TeamBlue or TeamRed) into a "Team" object? if this makes sense.
here is an example of what I'm trying to achieve:
Team team = new BlueTeam(); <-- storing any color team into a "team" object
this is a short version of the code I have:
class Team {
//empty class used for binding all the team classes
}
class BlueTeam extends Team {
public static List<String> players = new ArrayList<String>();
}
class PlayerData {
Team playerTeam;
public PlayerData(Team tm){
playerTeam = tm;
}
playerTeam.players // I want to access any subclass that is stored into this "myTeam" object and access its players list
}
class createData {
List<PlayerData> data = new ArrayList<PlayerData>();
// this is what I've tried but I get a null exception
Team team = new BlueTeam();
data.add(new PlayerData(team));
}
This is not object-oriented! Why does the blue team have a static list of players? Why is it public? You should use a getter and override the method.
abstract class Team {
// if there is a sensible default return then use it and the class needn't be abstract
abstract List<String> getPlayers();
}
class BlueTeam extends Team {
private final List<String> players = new ArrayList<>();
#Override
List<String> getPlayers() {
return players;
}
}
Usage:
Team team = new BlueTeam();
List<String> bluePlayers = team.getPlayers();
You're most likely doing class hierarchy wrong. Blue is not a property of a team, colour is. Meaning that instead of subclassing your Team for every possible colour, you should have a property called colour or name in Team and assign "blue" or "red" to that property in the instance of Team that represents the blue or red team.
Related
I have different weapon classes with various attributes and functions (some of which are similar). I am trying to iterate through objects of classes and trying to access those attributes based on certain conditions. Below are some of the objects I created and am storing inside an ArrayList of type Object.
Ak117 ak117 = new Ak117();
Ak47 ak47 = new Ak47();
Bk57 bk57 = new Bk57();
ArrayList <Object> weaponObjects = new ArrayList<>(Arrays.asList(ak117, ak47, bk57);
int damage = weaponObjects.get(0).damageStats;
//damage stats is an integer inside AK117 class that returns its damage
When I do this Eclipse can't identify .damageStats; and throws an error.
Is there any way wherein I can access all attributes or methods of these objects?
You can use Interface or Abtract class
Example
Create an interface that contains all the common methods of the classes:
public interface Weapon{
int getDamageStats();
void shoot();
// more method
}
Creat class implements this interface
class Ak47 implements Weapon{
#Override
public int getDamageStats() {
return 100;
}
#Override
public void shoot() {
System.out.println("Ak shoot");
}
}
class Bk47 implements Weapon{
#Override
public int getDamageStats() {
return 500;
}
#Override
public void shoot() {
System.out.println("Bk shoot");
}
}
Call List by Weapon:
Ak47 = new Ak47();
Bk47 = new Bk47();
ArrayList <Weapon> weaponsList = Arrays.asList(ak47, bk47);
int damage = weaponsList .get(0).getDamageStats();
you need something like the below:
ArrayList <Weapon> weaponsList = Arrays.asList(ak117, ak47, bk47);
If you only store the Objects you can only call the Object's methods for each array list entry. If you use Weapon (an interface for all weapons that defines getDamageStats()) all subclasses can then have this method called.
You need to write a getter in every weapon class.
public class Ak47 {
int damageStats;
public int getDamageStats() {
return damageStats;
}
}
You can access damageStats in another class by creating an instance of Ak47 and calling the getDamgeStats on it.
public class Example {
Ak47 ak47 = new Ak47();
int example = ak47.getDamageStats();
}
I think you should rethink adding inheritance, I am not a gun expert but maybe by country idk. Another option is with abstract class and just throw the methods that are common and modify the others. Then just like Rob Evans said iterate over a list, but my advise is to use new ArrayList<>(new Ak47(), ...etc) and not Arrays.asList.
Yep, this is a casual problem with the Object class. If you initiate your ArrayList as an Object, as someone already said, you'll only be able to reach Object Class's methods. By what you sent, we can think that your other classes share communs attributes. So the best idea would be to pass by a SuperClass, which will be extended by every others classes and have a getter on it (in this case, a getDamageStats()). Then you initiate your ArrayList as the SuperClass instead of Object and you'll be able to reach what you seem to want
I've been looking through some projects of games similar to the one I am developing and I've seen two ways of handling methods to mutate the Player.
Notes: a car, house, and job are the only three things to be handled. (only 3 items this game includes; - so a fourth item like family will never exist) However, this does not mean that no more fields will be added and mutated to the player class. (100+ more fields to be added)
Here is the generic java framework and usage (Which I am using at the moment):
#Data //lombok for setters/getters
public final class Player {
private final Car car = new Car();
private final Job job = new Job("none");
private final House hosue = new House();
public void makeHouseWooden() { //the method exists here in player class
house.setMode(wooden);
house.incrementTimesEdited(1);
house.refreshIfInside();
house.configureNewEnvironment();
}
}
This is what I've been seeing on other projects and would like to follow as the player class gets pretty big with methods:
#Data //lombok for setters/getters
public final class Player implements ContentWorker {
private final Car car = new Car();
private final Job job = new Job("none");
private final House hosue = new House();
#Override
public Player player() {
return this;
}
}
and the interface handles methods relating to the fields in Player.java
public interface ContentWorker {
Player player();
public default void makeHouseWooden() {
House house = player().getHouse();
house.setMode(wooden);
house.incrementTimesEdited(1);
house.refreshIfInside();
house.configureNewEnvironment();
}
}
I want to change to the second model because if I continue as I am at the moment then the Player class will become huge. (over 3000 lines)
This way I can keep the Player class for the fields only (better readability) and I could also have an interface which handles all house methods, another which handles all car methods and another which handles all job methods. (to avoid huge unreadable classes, also more dynamic interaction, easier to find the method you want)
public final class Player implements HouseWorker, CarWorker, JobWorker {
Which is better or more "efficient" and "easy to use" for my predicament?
I'm kinda new to Java, so I have a, rather dumb, question: Is it possible to have and use subclass'es objects in superclass which too have a constructor?
Here's an example what I want to do: I have Superclass Team and subclass Player. I want to create Player object, which contains variables like name, surname, height, etc. . And I want to access this Player object in Team class, which have it's name, positions and other variables, to assign the Player object to his position in the Team. Lets say, Player: John Doe is in Team named Red and he is a Goalkeeper.
And all together, is it possible to access all of this in main function? For example I want to print out all Team Red's players names.
Sorry, it's kinda complicated to explain what I want to do, but isn't this have to do something with extends?
The short answer is that yes, this is possible.
The longer answer is that you're misusing the terms superclass and subclass. The relationship you describe is not an is-a relationship of inheritance, but a has-a relationship of composition.
In other words, your Player class does not extend your Team class. Your Team class would contain instances of Player. And yes, in that case your Team class could access the methods and variables of those instances, just like you can any other Java class. It might look something like this:
class Team{
List<Player> players = new ArrayList<Player>();
public void addPlayer(Player p, String position){
p.position = position;
players.add(p);
}
}
And then from a main() method, you might do something like this:
public class Main{
public static void main(String... args){
Team team = new Team("Fighting Cats");
Player p = new Player("Johnny Appleseed");
team.addPlayer(p, "Apple Picker");
}
}
Yes, see the below code.
public class Team{
public Player player;
}
class Player extends Team{
public Team team;
}
Although, I doubt your logic and design when you say that Player extends Team, which essentially says that a Player is a Team. This would mean that each Player object would have a list of players and positions (as subtypes inherit non-private states and behaviours from supertypes), which doesn't make much sense semantically.
I suggest that you instead approach it like the following.
public class Team{
public LinkedList<Player> players;
}
class Player{
public Position position; // Use some way of defining the player's position.
}
This means that Team would have a Player, rather Player being a Team
What you are looking for is a composition and not inheritance (i.e. A Team "has a" Player. "A Player is a Team" does not make much sense)
class Player {
String name;
String surname;
String height;
}
class Team {
String name;
List<Player> players;
}
You have to create 3 classes Team, Player & a Client class to input the data.
I am writing the skeleton code for you. It will give you an idea as to how to write your code
public class Team {
ArrayList<Player> player;
public ArrayList<Player> getPlayer() {
return player;
}
public void setPlayer(ArrayList<Player> player) {
this.player = player;
}
}
Player
class Player{
String name;
Integer score;
Integer Rank;
//getter setters
}
Client class
public class Client {
public static void main(String[] args) {
Player pOne = new Player();
pOne.setRank(2);
pOne.setName("ABD");
Player pTwo=new Player();
pTwo.setRank(2);
pTwo.setName("SPC");
pTwo.setTotal(60);
ArrayList<Player> playerList = new ArrayList<Player>();
playerList.add(pOne);
playerList.add(pTwo);
Team team=new Team();
one.setPlayer(playerListOne);
//get the player using Team class's getPlayer method & print
}
You need not use extends but rather focus on the OO design.
When we think about team and player, its relation is team has a player.
Use the same relation when you design the classes.
Position is a property which is relevant in the scope of a Player. So introduce that property in correct level. Better to keep Team class with its own properties.
Here is a toy example of my conundrum:
public abstract class Car {
public Car(Seat[] seatsParam) { // Could be protected.
driverSeat = new DriverSeat();
seats = new ArrayList<Seat>();
seats.add(driverSeat);
seats.addAll(seatsParam);
}
private final List<Seat> seats;
private final DriverSeat driverSeat;
}
public class MyCar extends Car {
public MyCar() {
super(new Seat[]{new PassengerSeat()}); // Cannot assign to member.
}
public PassengerSeat getPassengerSeat() { // Would like this accessor.
return passengerSeat;
}
private final PassengerSeat passengerSeat;
}
Car has a list of Seat (the seat supertype), ideally initialized in the constructor. Every car has a DriverSeat. MyCar also has a PassengerSeat which I would like to access from the subtype, but also from the parent list (as a Seat).
Some things that I have shot down:
The code above: passengerSeat won't be initialized in the subclass. I could get the list in MyCar's constructor and downcast, but this is ugly.
Making passengerSeat static: it shouldn't be static since there could be many other MyCars with unique seats.
Have Car define an abstract getSubclassSeats() to which it adds driverSeat: this won't work in the constructor since passengerSeat won't have been initialized. I could make seats non-final and do it after the constructor but, again, ugly.
I want to say this is something I should be able to express in OO, define a variable and pass it to the parent to reference. But I cannot think of how to do it nicely. It's been awhile since I worked with C++, but is this what initialization lists solve? If so, does Java have an equivalent?
I've seen people with similar problems use thread-local variables and god knows what other awful tricks, luckily there's an easy solution:
public MyCar() {
this(new PassengerSeat());
}
private MyCar(PassengerSeat seat) {
super(new PassengerSeat[]{seat});
// Well do something with your seat now.
}
Currently I am designing a Monopoly game using Java.
Each player in the game can own different properties. The issue I'm having is how to assign different property objects to each player. I have both a Player class and a Properties class. Would composition be the best way to go about doing this? If so, how would I do it?
I would add a new class PropertyManager.
This allows you to easily provide business rules in a single location (good separation of concerns) rather than having to dive through a bunch of player or property objects if you opt for composition in either. This will keep the Player and or Property classes from becoming weighed down with buying/selling business rules in the future.
public final class PropertyManager {
/**
* The PropertyManager instance, example usage:
* PropertyManager.INSTANCE.buyProperty(property, buyer);
* NB: Good candidate for dependency injection instead if you are doing this.
*/
public static final PropertyManager INSTANCE = new PropertyManager();
private static final Map<Property, Player> propertyListing = new HashMap<Property, Player>();
/**
* Buy a property from the banker, banker or property manager could maintain
* Collection of available properties
*/
public void buyProperty(Player buyer, Property property) {
if (propertyListing.containsKey(property)) {
throw new IllegalStateException("Unable to buy unless owner sells it");
}
propertyListing.put(property, buyer);
}
/**
* Broker a transaction between two players for the sale of a property
*/
public void sellProperty(Player seller, Player buyer, Property property) {
if (!propertyListing.containsKey(property)) {
throw new IllegalStateException("Unable to sell Property which is not owned");
}
Player owner = propertyListing.get(property);
if (!owner.equals(seller)) {
throw new IllegalStateException("Unable to sell property seller doesn't own");
}
// TODO : Deduct/transfer monies (ensure sufficient value in buyer account etc)
propertyListing.put(property, buyer);
}
/**
* Retrieve a List of all of the Player's properties
*/
public List<Property> getProperties(Player owner) {
// TODO Either iterate through the propertyListing or use a second Map for player to List<Property>, NB: they should be guarded with a shared lock if you do this (threading).
}
/**
* Retrieve the owner of a Property or null if it is unowned
*/
#Nullable // javax annotation indiciates can be null
public Player getOwner(Property property) {
return propertyListing.get(property);
}
/**
* Hide the constructor as the only property manager should be INSTANCE
*/
private PropertyManager() {
// Prevent further instantiation
}
}
Think about it in real world terms.
When you're playing Monopoly and you purchase a property you take the property card and add it to your list of properties in front of you.
So in that case, you are a Player object adding Property objects to your property list.
public class Player
{
private List<Property> properties;
}
Composition works. As long as a player has a properties object, and the properties object contains all the necessary data, you should be fine (assuming you implement the necessary getter and setter methods).
the property can have an Owner property that is the Player.
You could also build a list on the Player of Properties.
You will need composition and polymorphism.
Assuming a player can have more than one property, you will need a List of properties. If Properties can differ in the attributes they have, you can apply Polymorphism and Inheritance. You will probably only see Inheritance below, but you will need Polymorphism when you are getting the different properties out and manipulating them.
In main:
public static void main(String args[]){
Player player1 = new Player();
BlackProperty blackProperty = new BlackProperty();
BlueProperty blueProperty = new BlueProperty();
player1.addProperty(blackProperty);
player1.addProperty(blueProperty);
}
All your domain classes:
public class Player{
private List<Properties> propertyList;
// getters and setters
public void addProperty(Properties properties){
if(this.propertyList == null){
this.propertyList = new ArrayList<Properties>();
}
this.propertyList.add(properties);
}
}
public class Properties{
private int noOfFloor;
// getters and setters
}
public class BlackProperty extend Properties{
private String noOfGate;
// getters and setters
}
public class BlueProperty extend Properties{
private String noOfLawn;
// getters and setters
}