I am completely new to Java.
I was practicing a code about a person eating some fruit. I have 3 classes
Fruit Class:
public class Fruit {
String fruitname = "grapes";
}
Person Class:
public class Person {
void eat(Fruit f) {
System.out.println("person is eating " + f.fruitname); // how can I do f.fruitname
}
}
Test Class:
public class TestFruit {
public static void main(String[] args) {
Person p = new Person(); // person object
Fruit f = new Fruit(); // fruit object
p.eat(f);
} // eat method of person class
}
output:
person is eating grapes
For accessing fields of a class, Object of that class is created.
My question is:
In Person class, how can I access fruitname field of Fruit class (i.e., writing f.fruitname) without instantiating Fruit class in Person class?
fruitname is a data member of Fruit class and instance member don't exist until object is created.
I have just started learning Java, and I am stuck here. Please help me to understand.
What you're doing does not work because you're not declaring the member field as public:
public String fruitname = "grapes";
Only then you can even compile this:
System.out.println("person is eating " + f.fruitname);
Note that in Java fields are package private per default (see also). This means that the field can be private but in this case you can only access this field in classes which reside in the same package.
However, in general one creates getter and setter methods like this:
public class Fruit {
private String fruitname = "grapes";
public String getFruitname() {
return fruitname;
}
public void setFruitname(String fruitname) {
this.fruitname = fruitname;
}
}
which will allow you to access the class member fruitname like this:
public class Person {
public void eat(Fruit f) {
System.out.println("person is eating " + f.getFruitname());
}
}
Depending on your IDE you might be able to right click the field (or somewhere in the class) and find something like Generate.. > Getters & Setters which makes the whole act less annoying.
Your problem is, that you dont encapsulate the Fruit class correctly.
The current field is package-private so only the class itself and other classes from the same package can access the field. When starting to use concurrency you really need to encapsulate your fields right in order to guard them aswell.
I suggest looking into the Annotation-Preprocessor Lombok since it will help you a lot by generating methods later on. You would just need to add two annotations above your class or the fields in it that should be encapsulated.
An encapsulated and documented version of your Fruit class would look like this:
package me.yourname.yourproject;
import javax.annotation.Nullable;
public class Fruit {
#Nullable
private String name;
/**
* Constructs a fruit without a name.
*/
public Fruit(){
}
/**
* Constructs a fruit with an initial name.
*
* #param name The fruits initial name.
*/
public Fruit(String name){
this.name = name;
}
/**
* Sets the name of the fruit.
*
* #param name The fruits new name.
*/
public void setName(#Nullable String name){
this.name = name;
}
/**
* Gets the fruits current name.
*/
#Nullable
public String getName(){
return this.name;
}
}
So it looks like you need to read up on Creating an object in Java. That's not a bad thing! OO design is hard when you're a beginner.
To answer you're question, you have to instantiate the fruitname object, and then mark it public (or preferably write a getter/setter)
public class Fruit {
private string name;
public Fruit(String name) {
this.name=name;
}
public String getName() {
return this.name;
}
}
Create this object with something like:
Fruit f=new Fruit("peach");
System.out.println(f.getName());
If what you want is to access it in Person without having an instance of Fruit:
Your fruitname is an instance variable. By declaring it 'static' you make it a class member and then you can access it using Fruit.fruitname
You can make it 'public' to allow access from anywhere. As in
public static string fruitname = "grapes";
Now you don't need an instance of Fruit to access fruitname.
Your Person call can look as follows:
public class Person {
void eat() {
System.out.println("person is eating " + Fruit.fruitname);
}
}
Related
I have an abstract class called Person.
A person has multiple child classes e.g. Driver, Sorter, Manager.
Each of which has its unique methods, and the ones shared e.g. name/age/location, etc and so I then thought that an abstract parent-class would be the solution. (Person)
Yet now I face a new problem, What if a person is both?
Now I have an 'Object' which is a Driver but also a Sorter.
So when he/she calls in sick, Person has a method called reportSick()
But when object driver.reportSick() is being called, there is a chance that there is another object for the same Person that is a Sorter.
It looks strange to me to have 2 objects for the same thing (The person in this case)
What am I overlooking/doing wrong/misunderstanding?
You can go this way:
Make the interface(or abstract class if needed) Profession and implement your classes (Driver, Sorter, Manager) from it.
Make Person not abstract and add there field List<Profession>. And when you need some methods call it in cycle for each Profession.
You've discovered one of the fundamental limitations of inheritance: It creates a very tight coupling between parent and child. "A Sorter is a Person". Not "A Sorter is some other kind of Person", but literally "A Sorter is directly an extension of Person and nothing else".
You can use composition to make explicit who to call next in the "inheritance" chain.
public interface Person {
public void reportSick();
}
public class OrdinaryPerson implements Person {
public void reportSick() {
// An "ordinary" person does nothing when they report sick.
}
}
public class Driver implements Person {
private Person next;
public Driver(Person next) {
this.next = next;
}
public void reportSick() {
// Driver specific stuff goes here ...
this.next.reportSick();
}
}
// Then do the same for Sorter and Manager ...
Now, if a person is "just" a driver, you can represent them as
new Driver(new OrdinaryPerson())
This person is both a driver and an ordinary person (OrdinaryPerson is our null object; it has no actual behaviors to speak of, so we can use it to break our chain).
If a person is both a driver and a sorter, we can write
new Driver(new Sorter(new OrdinaryPerson()))
and assuming Driver and Sorter each call the inner reportSick method, they'll both get called when you call the method on this aggregate we've constructed.
Driver, Manager & Sorter are just special kind of service that any person is efficient with. It may be one or more.
So, best way to declare interfaces for them and declare method for each without body.
Now declare class which extends abstract class & implements one or more interfaces.
public abstract class Person {
private String name;
private int age;
private String location;
// Constructor (Must)
public Person(String name, int age, String location) {
this.name=name;
this.age=age;
this.location=location;
}
}
public interface Driver {
void isDriving(String name, int age, String location);
}
public interface Sorter {
void isSorting(String name, int age, String location);
}
public interface Manager {
void isManaging(String name, int age, String location);
}
public class Person1 extends Person implements Driver, Manager {
/*
Properties, Constructors & Getters/Setters
*/
#overrides
public void isDriving(String name, int age, String location) {
// Driving Function Body
}
#overrides
public void isManaging(String name, int age, String location) {
// Managing Function Body
}
}
Beginner question - how do I avoid repeating code in sibling classes, where each has its own different version of the same field?
See example below: can I somehow move the getName() method (as well as far more complex methods) to the parent class?
public abstract class Car {
public abstract String getName();
}
public class PassengerCar extends Car {
private String name = "Passenger Car";
#Override
public String getName() { return name; }
}
public class CoalCar extends Car {
private String name = "Coal Car";
#Override
public String getName() { return name; }
}
You can, for example: create a constructor in the parent class which takes a name, and specify that name in the constructor of the child classes:
abstract class Car {
private String name;
public Car(String name) {
this.name = name;
}
public String getName() { return name; }
}
class PassengerCar extends Car {
public PassengerCar() {
super("Passenger Car");
}
}
class CoalCar extends Car {
public CoalCar() {
super("Coal Car");
}
}
Which then can be used like this:
Car passenger = new PassengerCar();
System.out.println(passenger.getName());
This prints out:
Passenger Car
#Mark's answer is the solution, but let me add a bit of background to it.
Simple rule of thumb: if you want something that all subclasses have in common, place it into the parent class.
What do you have?
a field called name used by all subclasses (it doesn't matter that the values are different, see below),
a getter called getName() used by all subclasses,
an initial value "Passenger Car" for all PassengerCar instances,
an initial value "Coal Car" for all CoalCar instances.
So, the name field and the getName() method go into Car, and the different initial values for that field go into the constructors of PassengerCar and CoalCar.
I have to decide whether the following two objects are immutable. I looked up the definition stating: “An object is considered immutable if its state cannot change after it is constructed”.
public class Car {
private int spareTires = 1;
private String model = "Volkswagen";
private Person driver = new Person();
public double engineSize = 2.0;
public int getSpareTires() { return spareTires; }
public String getModel() { return model; }
public Person getDriver() { return driver; }
}
public class Person {
private String name = "James";
public void setName(String s) { name = s; }
public String getName() { return name; }
}
Person isn't immutable since it has a mutator method (setName()).
However, I'm not sure about Car. Car doesn't have any mutator methods but according to https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html the fields must be declared final and static which isn't the case. Also I believe it's possible to change the state through public double engineSize = 2.0;?
However, I’m not sure about car. Car doesn’t have any mutator methods
but according to
https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html
the fields must be declared final and static which isn’t the case.
Not necessarily static, final is enough.
Also I believe it’s possible to change the state through ” public
double engineSize = 2.0; ” ?
Indeed, to be immutable, you don't have to expose as public the fields which describe the state of an instance. Otherwise, any client class of the instance may change engineSize.
Besides, this getter in the Car class does the Person modifiable since Person is not immutable :
public Person getDriver() { return driver; }
Car is not immutable since it has the driver property which is mutable and exposes the public engineSize method which is mutable. Also none of both classes is final.
I'm writing program that demonstrates the use of inheritance and I have created a variable using the super() keyword. I am now trying to place the value of that variable into a new method that calls it so that I can call that method in my main method to use its value within other classes.
Here is the relevant code:
Food class (super class)
public class Food {
//field that stores the name of the food
public String name;
//constructor that takes the name of the food as an argument
public Food(String name){
this.name = name;
}
public String getName() {
return name;
}
}
Meat class (sub class with super keyword)
public class Meat extends Food
{
public Meat() {
super("Meat");
}
public String getName() {
return //get super() value??;
}
}
Main class
public class Main {
public static void main(String[] args)
{
Wolf wolfExample = new Wolf();
Meat meatExample = new Meat();
System.out.println("************Wolf\"************");
System.out.println("Wolves eat " + meatExample.getName());
}
}
Any help is appreciated, thanks.
You could just do
public String getName() {
return super.getName();
}
Although you don't even need to override the method in the first place, because you declared the field name in super class to be public which means it can be accessed from anywhere.
Don't override public String getName() in Meat class.
The inheritance allows to inherit public and protected methods of Food in all subclasses of Food, therefore in Meat.
So Meat which IS a Food has by definition this behavior :
public String getName() {
return name;
}
which returns the name field stored in the parent class.
Overriding a method in subclass to write exactly the same code than in the parent method is useless and should not be done because it is misleading. A person which reads the code will wonder : why having overrided the method in the child class if it does the same thing than the parent class ?
Edit
Besides, if you want to access a field declared in a super class from a subclass, you should :
provide a public getter in the super class if the field is private. Here :
public String getName() {
return name;
}
use directly the field in the subclass if the field has the protected modifier.
As a general rule, you should avoid declaring instance fields with the modifier public because by default properties of a object should be protected and you should provide methods to modify the field only if needed.
So, declaring your Food class like that seems more suitable :
public class Food {
//field that stores the name of the food
private String name;
//constructor that takes the name of the food as an argument
public Food(String name){
this.name = name;
}
public String getName() {
return name;
}
}
In your Meat class, imagine you would like to add an additional information in the string returned by getName(), you could override it and why not using the field from the super class :
public class Meat extends Food {
public Meat() {
super("Meat");
}
#Override
public String getName() {
return super.getName + "(but don't abuse it)";
}
}
Here overriding the method is helpful because the behavior of the method in the child class differs from which one definedin the super class.
Simply write:
public String getName() {
return name;
}
This is because when searching for a variable named name, Java proceeds in this order:
Local variables (none)
Current class's fields (none)
Superclass's fields (found)
Super-super-class's fields (etc.)
However, you didn't need to override getName() in the subclass in the first place. If you didn't define it, then it would inherit the superclass's implementation, which corresponds exactly to the behavior you wanted. Thus you were doing extra work for no gain.
The other answers showed you how to do what you want.
But you should't do it (in real life projects)!
The most important principle in object oriented programming is encapsulation (aka information hiding). This means that the internal structure of a class should not be visible or accessible to the outside.
Therefore all member variables should be private.
Also you should avoid setter/getter methods since they just redirect the access. (except the class is a DTO without any logic of its own).
Since food class has the method getName declared as public do
public String getName() {
return super.getName();
}
I would like to create one class and then another class inside. This class will be directly connected with superior class. It should look like following (not code, just schema):
class company
string name
class employee
string firstName, lastName;
int age
Of course, I have constructors etc. Now I want to create company 'g' and employee f m of age 2 inside of that company. Maybe it is not justified to make class inside another class and I should just create class employee with field company?
Code below does not work, compiler says: an enclosing instance that contains company.employee is required
nowa=new company('g',2);
nowa.prac=new company.employee('f','m',2);
Full code below:
public class program
{
public static class company
{
char name;
int duration;
public class employee
{
public char imie,nazwisko;
public int wiek;
public employee(char a,char b,int w)
{
imie=a;
nazwisko=b;
wiek=w;
}
}
public company(char n,int c)
{
name=n;
duration=c;
}
}
public static void main(String []args)
{
company nowa=new company('g',2);
nowa.empl=new employee('f','m',2);
}
}
try
nowa.prac = nowa.new firma.pracownik('f','m',2);
Here is more on why:
http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
This would be my approach
public class Employee {
//...code
}
public class Company {
//...code
private List<Employee> employees;
}
public static void main(String []args)
{
Company nowa=new company('g',2);
nowa.getEmployees.add(new Employee('f','m',2));
}
}
The main changes from your approach are:
Both classes are in its own file (both are top level classes).
Company has an List of Employees (a company HAS employees). With a List you can add and remove easily employees for a given Company.
Class names are capitalized (according to Java naming conventions by using Upper Camel Case).
Your inner class employee is not static, so you need an instance of the outer class to create an inner class instance. An employee may not exist without a company!
company nows = new company('g',2);
nowa.empl = nowa.new employee('f','m',2);
In this case the inner class instances have an implicit reference to the outer class instance (use company.this inside employee to access it).
If you want to make the classes more independent, you can make employee a status inner class without the reference to the outer class:
public static class employee
...
company nows = new company('g',2);
nowa.empl = new employee('f','m',2);