What I should change to print the name of chair, which is chairNumber1?
public class Employee {
private Chair s;
Employee(Chair s) {
this.s = s;
}
void showData() {
System.out.println("Name of chair : " + s);
}
}
public class Chair {
}
public class Hlavna {
public static void main(String[] args) {
Chair s = new Chair("chairNumber1");
Employee c1 = new Employee(s);
c1.showData();
}
}
Why when I want to print name of the Chair, which is chairNumber1, Java prints on console the address of chairNumber1, but not it's name?
You must be already aware of the fact that every class in Java inherits a class called Object by default. This class has a method toString() which returns a string consisting of the name of the class of which the object is an instance, the at-sign character `#', and the unsigned hexadecimal representation of the hash code of the object.
When you use System.out.println("Name of chair : " + s);, it will call s.toString() but since you haven't provided your own implementation of toString() inside class Chair, it will call the toString() method of class Object which is the default superclass of class Chair. This is why you see the value which you think as the address of chairNumber1.
To get your desired String, you need to override the toString() method something like:
public class Chair {
private String name;
public Chair(String name) {
this.name = name;
}
public String toString() {
return name;
}
}
define a method inside your chair class that returns the name or override the toString method.
example:
public class Chair{
private String chairName;
Chair(String chairName){
this.chairName = chairName;
}
public String toString(){
return chairName;
}
}
now inside showdata() call toString():
void showData(){
System.out.println("Name of chair : " + s.toString());
}
There are a couple of things going on here.
You have created a chair object in your main method of your Hlavna class. To this Chair object you have provided an argument, although from the code above Chair does not take an argument.
In the same way that you have made the Employee class take an argument of chair, you should take the Chair take an argument of name, like so:
public class Chair
{
private String name;
Chair(String chairName)
{
this.name = chairName;
}
}
Now this isn't enough. When you print any Java object, under the hood what is really happening is the object's toString method is called. By default this prints the object's address, but you can override that by implementing the method yourself, like so:
public class Chair
{
private String name;
Chair(String chairName)
{
this.name = chairName;
}
public String toString()
{
return this.name;
}
}
Now, when you print a chair object it will call the Chair object's implementation of toString, which here returns the chair's name.
Your employee class is correctly printing the "toString()" method of the chair that you pass to it as you construct it, but currently that looks like an address. If you change the Chair object to the above code, that will instead print the chair name, which is what you are after.
The full code would look like this:
public class Employee
{
private Chair s;
Employee(Chair s)
{
this.s = s;
}
void showData()
{
System.out.println("Name of chair : " + s);
}
}
public class Chair
{
private String name;
Chair(String chairName)
{
this.name = chairName;
}
public String toString()
{
return this.name;
}
}
public class Hlavna
{
public static void main(String[] args)
{
Chair s = new Chair("chairNumber1");
Employee c1 = new Employee(s);
c1.showData();
}
}
public class Chair {
private String name;
public Chair(String name) {
this.name = name;
}
#Override
String toString() {
return name;
}
}
Related
Im practicing polymorphism and inheritance, and i made a class (Animals) that sets the name of the animal, then i made a subclass (Cat) that sets the sound it makes, favourite toy.. all that. i tried testing it in a seperate class (Test) to print out "Cat likes to Moew, its favourite toy is Yarn" but its not working unless i extend Cat in the test class.
Heres my code.
Animals.java
public class Animals {
protected static String name;
public Animals() {
}
public Animals(String name) {
this.name = name;
}
public String setName(String newName) {
return this.name = newName;
}
public String getName() {
return name = name;
}
public static void animMove() {
System.out.println(name + " likes to walk");
}
}
Cat.java
public class Cat extends Animals {
public static String sound;
public static String favToy;
public String getSound(String sound) {
return this.sound = sound;
}
public String getToy(String favToy) {
return this.favToy = favToy;
}
public Cat() {
}
public Cat(String name, String sound, String favToy) {
super(name);
this.sound = sound;
this.favToy = favToy;
}
}
test.java
public class test{
public static void main(String[] args) {
Animals anim = new Animals();
Cat cat = new Cat("Cat", "moew", "Yarn ball");
System.out.println(anim.getName() + " Likes to " + cat.getSound(sound)
+ ", its favourite toy is a " + cat.getToy(favToy));
}
}
All works fine if i extend Cat to the test class, but when i dont, none of the variables like sound and favToy work. how would i do this without extending anything to the test class
Do not make the name variable static. This would mean that it belongs to the class and not an Animal object, meaning there will only ever be one Animal.name in the class. Your Cat.sound, Cat.favoriteToy variables are also static, which will mean all cats will have the same sound and same favorite toy (I guess this is acceptable, but then dont assign this in a constructor).
Setters don't need to have a return value (you are only changing some variable). For example:
public void setName(String newName) {
this.name = newName;
}
Getters do not need any parameters. You already know what to return, no need for a parameter. For example:
public String getSound() {
return this.sound;
}
Also, your Animals should be Animal, as this class represents a single animal.
If you create a Cat object, this will automatically be Animal as well (its inherited), so no need to create both, as you do in your main method
Cat myCat = new Cat("Purr","meow","ball"); //create cat
System.out.println(myCat.getName());
variables are static so all cats will have this name, sound and fav toy now...
Maybe you tried to do something like
1)
public class Animal {
protected String name;
public String animMove() {
return new String(this.name + " likes to walk");
}
}
2)
public class Cat extends Animal {
public String sound;
public String favToy;
public Cat(String name, String sound, String favToy) {
super(name);
this.sound = sound;
this.favToy = favToy;
}
public String getName() {
return super.name;
}
public String getSound() {
return this.sound;
}
public String getToy() {
return this.favToy;
}
}
3)
public class test{
public static void main(String[] args) {
Animal anim = new Cat("Cat", "moew", "Yarn ball");
System.out.println(anim.getName() + " Likes to " + anim.getSound(sound) + ", its favourite toy is a " + anim.getToy(favToy) + " " + anim.animMove());
}
}
I have a basic inheritance situation with an overloaded method in the super class.
public class Person {
private String name;
private int dob;
private String gender;
public Person(String theName, int birth, String sex){
name = theName;
dob = birth;
gender = sex;
}
public void work(){
getWorkDetail(this);
}
public void getWorkDetail(Employee e){
System.out.println("This person is an Employee");
}
public void getWorkDetail(Person p){
System.out.println("This person is not an Employee");
}
}
The following Employee class extends the Person class above:
public class Employee extends Person {
String department;
double salary;
public Employee(String theName, int birth, String sex){
super(theName, birth, sex);
department = "Not assigned";
salary = 30000;
}
}
The main method simply creates an Employee object (both static and dynamic type) and calls .work() on it:
public static void main(String[] args){
Employee e1 = new Employee("Manager1", 1976, "Female");
e1.work();
}
This ends up printing
This person is not an Employee
Looking through this I had thought that since both the static and dynamic type of the object e1 is Employee it would call the overloaded method in Person that takes an Employee as a parameter. Since I am clearly wrong about this I opened a debugger assuming the reference to "this" at the line getWorkDetail(this) in the Person class must have morphed to it's super class. However this is not what I found.
Clearly at this point in the code this is an Employee object, however it still chose to execute the overloaded method getWorkDetail(Person p). Can anyone explain this behavior?
Unlike method overrides, method overloads are linked based on the static type. And in this case, getWorkDetail(this) in Person only knows about the Person type.
Method overloading is not designed to provide dynamic runtime behavior.
To take advantage of dynamic binding, you may need to redesign your code to override the methods, instead:
public static void main(String[] args) throws IOException {
new Employee("Manager1", 1976, "Female").getWorkDetail();
new Person("Manager1", 1976, "Female").getWorkDetail();
}
And modify behavior based on implementing classes. Of course, you can overload methods, as long as you take care of overriding the overloaded methods too, if required.
class Person {
private String name;
private int dob;
private String gender;
public Person(String theName, int birth, String sex) {
name = theName;
dob = birth;
gender = sex;
}
public void getWorkDetail() {
System.out.println("This person is not an Employee");
}
}
class Employee extends Person {
String department;
double salary;
public Employee(String theName, int birth, String sex) {
super(theName, birth, sex);
department = "Not assigned";
salary = 30000;
}
public void getWorkDetail() {
System.out.println("This person is an Employee");
}
}
The overload resolution happens during compile time, not at runtime.
So, when you call getWorkDetails(this), this is assumed to be a Person (which is the static type) and hence called the corresponding overload.
Note: Using this inside Employee class would have made it an Employee type. You can verify this by overloading work() in Employee like this.
class Employee extends Person {
...
public void work() {
getWorkDetails(this); // This should print "This person is an Employee"
}
}
Problem specific solution
In some languages parameters are resolved to their dynamic type, but not in java. The compiler already determines at compile time where your getWorkDetail(this); will go. this is of type Person, so getWorkDetail(Person e) is called. In your specific case the solution is quite obvious. As others have already pointed out, you'll need to override getWorkDetail() in the Employee class.
Resolving methods to their dynamic parameter types
To solve the general problem of resolving parameter types at runtime, using the instanceof operator should be avoided, as it usually leads to unclean code.
If you have two different classes, a solution as simple as stated above is no longer possible. In these cases you'll have to use the visitor pattern.
Consider the following classes:
public interface Animal {
default void eat(Food food) {
food.eatenBy(this);
}
void eatMeat(Meat meat);
void eatVegetables(Vegetables vegetables);
}
public class Shark implements Animal {
public void eatMeat (Meat food) {
System.out.println("Tasty meat!");
}
public void eatVegetables (Vegetables food) {
System.out.println("Yuck!");
}
}
public interface Food {
void eatenBy(Animal animal);
}
public class Meat implements Food {
public void eatenBy(Animal animal) {
animal.eatMeat(this);
}
}
public class Vegetables implements Food {
public void eatenBy(Animal animal) {
animal.eatVegetables(this);
}
}
Which you can call like this:
Animal animal = new Shark();
Food someMeat = new Meat();
Food someVegetables= new Vegetables();
animal.eat(someMeat); // prints "Tasty meat!"
animal.eat(someVegetables); // prints "Yuck!"
Following the visitor pattern calling Animal.eat will call Food.eatenBy, which is implemented by both Meat and Vegetables. Those classes will call the more specific eatMeat or eatVegetables method, which uses the correct (dynamic) types.
Call preference
class Foo {
static void test(int arg) { System.out.println("int"); }
static void test(float arg) { System.out.println("float"); }
static void test(Integer arg) { System.out.println("Integer"); }
static void test(int... arg) { System.out.println("int..."); }
public static void main(String[] arg) {
test(6);
}
}
The output will be int printed on console. Now you comment the first test() method and see what is the output coming.
This is the preference hirarchey in primitive data types. Now coming to derived types declare a class FooChild like this
class FooChild extends Foo {
}
and create two new methods in Foo like
static void testChild(Foo foo) { System.out.println("Foo"); }
static void testChild(FooChild fooChild) { System.out.println("FooChild"); }
then in main method try calling testChild like this testChild(new FooChild());.
getWorkDetail(this) does not know what the subclasses are. call getWorkDetail instead.
say we have 2 classes:
public class A {
private String name = "A";
public String toString()
{
return (name + "some random text");
}
}
public class B extends A{
private String name = "B";
public String toString()
{
return (super.toString());
}
}
When I tried to print the B.toString() in my driver class, it will still print the name from class A instead of the name from class B. How can I change it so it will use the variable name from class B instead?
You can do it through the use of constructors -
public class HelloWorld {
public static void main(String[] args) {
A a = new A("A String");
B b = new B("B String");
System.out.println(a.toString()); // A String some random text
System.out.println(b.toString()); // B String some random text
}
}
class A {
protected String name;
A(String name) {
this.name = name;
}
public String toString() {
return name + " some random text";
}
}
class B extends A {
B(String name) {
super(name);
}
#Override
public String toString() {
return (super.toString());
}
}
Because B inherits from A, the name field is setup correctly when you pass a string to the constructor for B.
I have my Pet super class which then has a Dog subclass, and a particular method in my super class is getSpecies(). In my subclass I want to be able to return super.getSpecies(), but also return another variable (in this case, smell) inside that method as well.
Super class:
public class Pet {
protected int lifeSpan;
protected String species, name, interaction;
public Pet(){
}
public Pet(int lifeSpan, String species, String name){
this.lifeSpan = lifeSpan;
this.species = species;
this.name = name;
}
public final float costs(float cost){
return cost;
}
public void setSpecies(String species){
this.species = species;
}
public String getSpecies(){
return this.species;
}
}
Subclass "Dog":
public class Dog extends Pet{
protected String smell;
private String species;
public Dog(String smell){
super(15, "Dog", "Rex");
this.smell = smell;
}
public Dog(){
}
public void setSmell(String smell){
this.smell = smell;
}
public String getSpecies(){
super.getSpecies();
smell = "high"; //Meant to deliberately set it to "High". How am I to return this?
}
public String getSmell(){
return this.smell;
}
}
You cannot return two values in a single function. What you have to do is use your getter for the smell member variable instead.
public class Dog extends Pet{
protected String smell;
private String species;
public Dog(String smell){
super(15, "Dog", "Rex");
this.smell = smell;
}
public Dog(){
}
public void setSmell(String smell){
this.smell = smell;
}
public String getSpecies(){
super.getSpecies();
}
public String getSmell(){
return this.smell;
}
}
Then let's say you want both species and smell, you have to check if the pet is in fact a dog, and if it is, you can safely cast it as a dog and use the specific methods of the Dog class.
if ( pet instanceof Dog ) {
String species = pet.getSpecies();
String smell = (Dog)pet.getSmell();
}
First things first: When calling super.getSpecies() you should save or hand over it's return value somewhere. Then you might consider concatenating this return string an your second return value (high) like this:
public String getSpecies(){
return "high " + super.getSpecies();
}
But:
the return of that high dog doesn't make much sense IMO.
a getter is expected to return only one value, the one it's name comes from.
There is no ather way to return multiple values except for passing objects that take the results as arguements. But that solution would be far away from a simple getter.
You should consider (like Pilibobby pointed out in his comment below) using two different getters in your case, getSpecies() and getSmell(), and combine their results at the place you are calling them from.
Customer.java:17: error: cannot find symbol
super.display();
^
symbol: method display()
1 error
This what is happening when I compile my program. How do I display the objects data in the Customer subclass?
import java.util.Scanner;
public class Person {
private String name;
private String address;
private String number;
//No Argument constructor//
public Person() {
name = "";
address = "";
number = "";
}
//Explicit value constructor//
public Person(String num, String nam, String add) {
number = num;
name = nam;
address = add;
}
//Accessor method//
public String getName() {
return name;
}
//Mutator method//
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getTelephoneNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
public String toString() {
return name + "\n" + address + "\n" + number;
}
}
The subclass:
public class Customer extends Person {
public Customer(String num, String nam, String add) {
super(num, nam, add);
}
public boolean checkResponse(char response) {
if (response == 'Y') {
return true;
}
return false;
}
public void display() {
super.display();
}
}
In order for super.display() to work, you require a method called display() in your parent class.
Since you have no such method, Java will not allow the code you have to compile.
Since it seems you're trying to show useful information about the object when it's printed, why not override toString() again? The caveat here is that you don't have any more meaningful information to show about it being a Customer over it being a Person (there's no Customer-specific fields, so the inheritance relationship is moot).
You may want to consider adding more info to differentiate a Customer from a Person, then override toString().
The error occurs because there is no display() method in the Person class. So you cant invoke a non existing method using super.display()
So change the display() method in Customer to
public void display() {
System.out.println(super.toString());
}
As the error is trying to tell you, super.display() doesn't exist.
You can simply access the number, name or address directly. Modify the display() method, remove super.display() like below.
public void display()
{
System.out.println("Customer telephone number:" + number);
}
Super keyword in java is related to parent class and Super.display() means you are calling the display method of the parent class.Your parent class is person as you are extending it public class Customer extends Person {
But there is no display() in person hence your are getting compilation error
You don't have display() function defined in parent class(Pesron);