How to typecast this class? - java

I have this super class called BasketBallPlayer
I have a child class called ProBasketBallPlayer
If I create an object
BasketBallPlayer bp1;
bp1=new BasketBallPlayer("Tim Duncan", "Center", "Spurs", 83, 220, 4, 5, 8);
public class BasketBallPlayer {
protected String name;
protected String position;
protected String team;
protected int height;
protected int weight;
protected int agility;
protected int speed;
protected int ballHandling;
public BasketBallPlayer() {
this.name = "unknown";
this.position = "unknown";
this.team = "unknown";
this.height = 0;
this.weight = 0;
this.agility = 0;
this.speed = 0;
this.ballHandling = 0;
}
public BasketBallPlayer( String name, String position, String team)
{
this.name = name;
this.position = position;
this.team = team;
this.height = 0;
this.weight = 0;
this.agility = 0;
this.speed = 0;
this.ballHandling = 0;
}
public BasketBallPlayer (String name, String position, String team, int height, int weight,
int agility, int speed, int ballHandling)
{
this.name = name;
this.position = position;
this.team = team;
this.height = height;
this.weight = weight;
this.agility = agility;
this.speed = speed;
this.ballHandling = ballHandling;
}
How can I typecast it to ProBasketballPlayer without getting ClassCastException
Here are the ProBasketballPlayer constructors
public class ProBasketballPlayer extends BasketBallPlayer {
protected int yearsInLeague;
protected String role;
public ProBasketballPlayer()
{
super();
yearsInLeague = 0;
role = "bench";
}
public ProBasketballPlayer( String name, String position, String team )
{
super(name, position, team);
this.name = name;
this.position = position;
this.team = team;
yearsInLeague = 0;
role = "bench";
}
public ProBasketballPlayer(String name, String position, String team, int height, int weight,
int agility, int speed, int ballHandling, int yearsInLeague, String role)
{
super(name, position, team, height, weight, agility, speed, ballHandling);
this.yearsInLeague = yearsInLeague;
this.role = role;
}

You cannot. Casting doesn't change anything about an object, it just tells the compiler that it can interpret the object as a class that is further up the class hierarchy, but not down. Once you instantiate an object, that's it - that object is definitely and irrevocably a member of the class you instantiated. It is a BasketballPlayer, and never will be a ProBasketballPlayer. If you want a Pro, instantiate one - you'll be able to use the Pro as a normal Basketball player, but not vice versa.
As an example:
class Foo
{
int a;
}
class Bar extends Foo
{
int b;
}
Foo obj = new Foo();
obj.a = 0; // our obj has an "a" field because it is a Foo.
obj.b = 0; // but no "b" field, because it is not a Bar.
// It therefore makes no sense to do this:
((Bar)obj).b = 0; // because that's the same as trying to do "obj.b"
// in either case, "obj" is not a "Bar", and cannot have a "b" field. "obj" will always be a "Foo", never a "Bar".
//
// If however we make a Bar:
Bar obj2 = new Bar();
// we can access both fields, since Bar has both of them
obj2.a = 0;
obj2.b = 0;
// and, since Bar is a SUPERSET of Foo (all Bar are Foo, not all Foo are Bar),
// we can even use obj2 as a Foo, and pass it to methods which accept a Foo.

How can I typecast it to ProBasketballPlayer without getting
ClassCastException
You can't cast in the wrong direction. Think about the following two statements...
ISA BasketballPlayer a ProBasketballPlayer?
Are all BasketBallPlayers ProBasketBall players?
No. I play basketball and I'm not a pro basketball player.
Is every Bird a Duck.
Bird b = new Bird();
Duck daffy = (Bird)b;
daffy.quack(); // Error here, not all birds quack?

You can't cast an object to a subclass. Objects can only be casted "downward" from what their constructor's type was. Every Cat is an Animal, but not every Animal is a Cat. Casting only goes one way.
What you can do is create a constructor in ProBasketballPlayer that accepts a BasketBallPlayer and copies in the relevant fields. Make sure to initialize any additional fields that ProBasketballPlayer may have also.
public ProBasketballPlayer(BasketBallPlayer bbp, int yearsInLeague, String role) {
super(bbp.getName(), bbp.getPosition(), bbp.getTeam(), bbp.getHeight(), bbp.getWeight(), bbp.getAgility(), bbp.getSpeed(), bbp.getBallHandling());
this.yearsInLeague = yearsInLeague;
this.role = role;
}
public public ProBasketballPlayer(BasketBallPlayer bbp) {
this(bbp, 0, "bench");
}
If ProBasketballPlayer is in the same package as BasketBallPlayer, then you can access the fields directly (e.g. bbp.name) instead of using getters.

Related

Java interfaces and objects

Over here i'm trying to make use of an interface called "Measurable" with one method called getMeasure. The problem is, I'm trying to get the average height of all the people in my program, by accessing the method in my interface. One of the problems I can't access the getMeasure method for some reason, and at last get the average height of all the people in the array. How can I solve this problem?
class Main {
public static void main(String args[]) {
Person[] people = new Person[4];
people[0] = new Person("Larry", 65);
people[1] = new Person("Susan", 45);
people[2] = new Person("Joe", -45);
people[3] = new Person("", 0);
double averageHeight = average(people);
}
public static double average(Person[] objects)
{
if (objects.length == 0) { return 0; }
double sum = 0;
for (Person obj : objects)
{
double measure = obj.getMeasure();
sum = sum + measure;
}
double result = sum / objects.length;
return result;
}
}
interface Measurable {
double getMeasure();
}
public class Person {
private String name;
private Integer height;
public Person(String name, Integer height)
{
this.name = name;
this.height = height;
}
public double getMeasure() {
return height;
}
}
The Person class should implement Measurable:
public class Person implements Measurable {
...
}
Then if you want to make your average function reusable (I guess this is your desired outcome), you should replace the Person instance with Measurable:
public static double average(Measurable[] objects) {
...
for (Measurable obj : objects){
...
}
}
This way you could have different Measurable implementations to calculate the average.
public class Person implements Measurable {
private String name;
private Integer height;
public Person(String name, Integer height)
{
this.name = name;
this.height = height;
}
#Override
public double getMeasure() {
return height;
}
You have to implement the to use it. If the Interface also implements the method, you have to add the #Override modifier.

The constructor Teacher(Teacher) is undefined

I am using a copy constructor and Inheritance in a class called 'Department' to call the information from class 'Teacher' which is a sub-class of 'Person'. After creating my set/get methods, I get the above error. Anyone have any insight as to why this is occurring?
Code from 'Department' class:
public class Department {
private String deptName;
private int numMajors;
private Teacher[] listTeachers; //inherits from Person class
private Student[] listStudents; //inherits from Person class
// First constructor for Department
public Department(String dn, int nm, Teacher[] listTeachers, Student[] listStudents) {
this.deptName = dn;
this.numMajors = nm;
this.listTeachers = new Teacher[listTeachers.length];
for (int i = 0; i < this.listTeachers.length; i++)
{
this.listTeachers[i] = new Teacher (listTeachers[i]);
}
//set method for Teachers Array
public void setListTeachers (Teacher[] other) {
this.listTeachers = new Teacher[other.length];
for (int i = 0; i < listTeachers.length; i++) {
this.listTeachers[i] = new Teacher (other[i]);
}
}
//get method for Teachers Array
public Teacher[] getListTeachers() {
Teacher[] copyTeachers = new Teacher[listTeachers.length];
for (int i = 0; i < copyTeachers.length; i++) {
copyTeachers[i] = new Teacher(this.listTeachers[i]);
}
return copyTeachers;
}
Here are the lines giving me errors:
1) this.listTeachers[i] = new Teacher (listTeachers[i]);
2) this.listTeachers[i] = new Teacher (other[i]);
3) copyTeachers[i] = new Teacher(this.listTeachers[i]);
Code from 'Teacher' class:
public class Teacher extends Person {
private String id;
private int salary;
private int num_yr_prof;
//Constructor for use in Teacher main method.
public Teacher(String n, int a, String s, boolean al, String i, int sal, int numyr) {
super(n, a, s, al);
this.id = i;
this.salary = sal;
this.num_yr_prof = numyr;
}
//Copy constructor for use in Department class.
public Teacher (String n, int a, String s, boolean al, Teacher other) {
super(n, a, s, al);
if (other == null) {
System.out.println("Fatal Error!");
System.exit(0);
}
this.id = other.id;
this.salary = other.salary;
this.num_yr_prof = other.num_yr_prof;
}
Your copy constructor might look like this:
public Teacher(Teacher teacher) {
this( teacher.n, teacher.a, teacher.s, teacher.al,
teacher.id, teacher.salary, teacher.num_yr_prof );
}
Since you do not show the code for the Person class, I have used the variable names n, a, s, and al here. They should be replaced by whatever those variables are named in the Person class. This, of course, assumes that those variables are either public or protected. If they are private, you need to use the getters for those variables (preferred even if they are public or protected).
You need to to your Teacher class a constructor that accepts a Teacher:
public Teacher(Teacher teacher) {
// do something
}

Reference leaks in copy constructor

I understand what is the reference leak and can deal with it, but I'm confused now when I had to write a copy constructor. Does the copy constructor cause leaks too?
public class Student {
private final int ID;
private final String studentName;
private double[] Grades = new double[5];
// constructor:
public Student(int ID, String Name, double[] quizGrades) {
this.ID = ID;
this.studentName = Name;
this.Grades = new double[quizGrades.length]; // use new to avoid REFERENCE LEAKS...
for (int k = 0; k < quizGrades.length; k++) //
this.Grades[k] = quizGrades[k]; //
}
// Copy constructor:
public Student(Student stu) {
this(stu.ID, stu.studentName, stu.Grades);
}
}
I made a copy of array quizGrades so there will not be a leak, but I am not sure whether the copy constructor is fine or not.

Return type required/ Cannot return a value from a method with a void result type

Im a beginner, can you tell me what am i doing wrong? Why can't i use those methods properly?
IDE shows: Return type required/ Cannot return a value from a method with a void result type
` public class Human
{
public int Age = 0;
public int Weight = 0;
public int Height = 0;
private String name = "";
boolean isMale;
}
public getAge()
{
return Age;
}
public getWeight()
{
return Weight;
}
public getHeight()
{
return Height;
}
public Human(int Age, int Weight, int Height, String name, boolean
isMale)
{
} `
Great job so far, you're just missing the return type statements for your methods. Your methods should be written as follows:
class Human {
private int Age = 0;
private int Weight = 0;
private int Height = 0;
private String name = "";
private boolean isMale;
public int getAge() {
return Age;
}
public int getWeight() {
return Weight;
}
public int getHeight() {
return Height;
}
public Human(int Age, int Weight, int Height, String name, boolean isMale) {
this.Age = Age;
this.Weight = Weight;
this.Height = Height;
this.name = name;
this.isMale = isMale;
//returns nothing
}
}
Notice that each method has some sort of return type. Since getAge() returns Age (which you have specified above as type int), you need to explicitly put in the method declaration statement that you are returning an int. Same holds true if you were to return a String or a Boolean, etc.
The last method (Human()), however, is a constructor function that gets called when you instantiate a new Human object:
Human myHuman = new Human(31, 155, 68, "Bob", true);
Notice how in the codeblock above, I am passing values in the order that I have them in the constructor function and the constructor function sets the attributes of the object based on what is being passed. The big takeaway here, per your question, is that it does not return anything (with the exception of a new object...discussion for another time).
Generally speaking, if you are not returning anything, put void in the return type. Just as you do in the Main function.
Last thing that I would like to point out, is the use of public vs. private for your attributes and methods. Generally speaking, you would set your attributes to private and then make your public get/set methods to return or alter these attributes. Just something to look out for in the future.
Hope that helps! Feel free to message me if you have another question or need some clarification.
You need to have a return type for each function from where you want to return a value.
ex:
public int getAge()
{
return Age;
}
public int getWeight()
{
return Weight;
}
public int getHeight()
{
return Height;
}
You need to specify a return value after each method modifier.
For example,
public int getAge() {
return age;}

How to use a constructor to initialize a different class's object in Java?

public class Location {
final public static int INITIAL = 0;
final public static int PRISON = 1;
final public static int DEATH = 2;
final public static int SQUARE = 3;
private String name;
private int type;
private int section;
private int damage;
private Square square ;
// this constructor construct a Location from a name and a type.
public Location(String name, int type) {
this.name = name;
this.type = type;
}
// this constructor constructs a Location of type SQUARE from a name, section, and damage.
public Location(String name, int section, int damage) {
this.name = name;
this.section = section;
this.damage = damage;
this.square = new Square(name,section,damage);
}
// Get the square associated with this Location.
public Square getSquare() {
return square;
}
}
I think I'm misunderstanding what the second constructor is doing, as currently the constructor isn't doing anything to the instance variable square.
In your second constructor, you just have to initialize type with Location.SQUARE:
// this constructor constructs a Location
// of type SQUARE from a name, section, and damage.
public Location(String name, int section, int damage) {
this.name = name;
this.section = section;
this.damage = damage;
this.type = Location.SQUARE;
this.square = new Square(name,section,damage);
}
And now your class' attributes will be consistent.
Regarding initialization of the square attribute, it seems to be OK to me. You can create instances of other classes inside a constructor and assign them to attributes if you want.
In your second constructor you are simply initializing your property - private Square square of your Location class from the parameters you provided to the constructor.
Initializing an Object/non-primitive (eg.- square here) type is completely valid in java like initializing other primitive type (eg. - type, section etc here)
You have a problem: Your first constructor does nothing with the Square reference, so it's null.
Try it like this:
/**
* #link http://stackoverflow.com/questions/31523704/how-to-use-a-constructor-to-initialize-an-different-classs-object-in-java
* User: mduffy
* Date: 7/20/2015
* Time: 3:07 PM
*/
public class Location {
final public static int INITIAL = 0;
final public static int PRISON = 1;
final public static int DEATH = 2;
final public static int SQUARE = 3;
private String name;
private int type;
private int section;
private int damage;
private Square square;
// No idea what damage ought to be. Is that your type?
public Location(String name, int type) {
this(name, Location.SQUARE, type);
}
public Location(String name, int section, int damage) {
this.name = name;
this.section = section;
this.damage = damage;
this.square = new Square(name, section, damage);
}
public Square getSquare() {
return square;
}
}

Categories