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
}
}
Related
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 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);
}
}
I am wondering how to convert overlapping type of inheritance to Java. I got abstract class Person, and 2 extending subclasses: Driver and Passenger. As you know, driver may also be a passenger. So the question is: what's the best way to implement overlapping in Java? I heard that the best way is to use the composition, but i don't know how to.
When a single class can play two roles in a system, an inheritance-based approach in Java is to define two interfaces, and have the class implement them:
interface Passenger {
... // Methods applicable to passengers
}
interface Driver {
... // Methods applicable to drivers
}
class Person implements Driver, Passenger {
... // A person can be a driver or a passenger
}
class Pet implements Passenger {
... // A pet can be only a passenger
}
You can use composition internally to implement the interfaces by forwarding method calls to private helper "passenger" and "driver" objects inside Person.
In Java-8 you can place logic that is common to all implementing classes into default method implementations.
This is an extension of the answer provided by dasblinkenlight.
The solution is based on the component pattern described here by the Team Leader of the Tony Hawk dev team back in the '90s and it's often used in game development.
Disclaimer: I'm going to write the code without a Java compiler so please do tell me whether there are syntax errors.
Your abstract class Person
abstract class Person {
public String name;
}
This way we expose the behaviour of Driver
interface DriverInterface {
public void drive();
}
And here we export the behaviour of Passenger
interface PassengerInterface {
public void seat();
}
Here we put the actual logic of a Driver
class DriverComponent {
private Person person;
public DriverComponent(Person person) {
self.person = person;
}
public void drive() {
System.out.println("I'm" + person.name + " and I'm driving");
}
}
And here we put the logic of Passenger
class PassengerComponent {
private Person person;
public PassengerComponent(Person person) {
self.person = person;
}
public void drive() {
System.out.println("My name is " + person.name + " and I'm passenger");
}
}
Finally the Driver class
class Driver extends Person implements DriverInterface, PassengerInterface {
private DriverComponent driverComponent;
private PassengerComponent driverComponent;
private String name;
public Person(String name) {
driverComponent = DriverComponent(this);
passengerComponent = PassengerComponent(this);
}
public void drive() {
driverComponent.drive();
}
public void seat() {
passengerComponent.seat();
}
}
And the Passenger class
class Passenger extends Person implements Passenger {
private DriverComponent driverComponent;
private PassengerComponent driverComponent;
public String name;
public Passenger(String name) {
driverComponent = DriverComponent(this);
passengerComponent = PassengerComponent(this);
}
public void seat() {
passengerComponent.seat();
}
}
Wrap up
I really hope there are not syntax errors.
The power of this approach is that we do not replicate the logic of a Driver or of a Passenger because we write this code only once inside the related component.
The Component approach also allow us to easily create (and maintain) even combination of entity (like Driver, Passenger) and behaviour (DriverInterface, PassengerInterface) simply combining the related component.
It's the best alternative to multiple inheritance not supported by Java and it way better and clearer.
Similar to dasblinkenlight's answer, but I think more technically correct:
interface Person{}
interface Pet{}
interface HumanPassenger extends Person{}
interface PetPassenger extends Pet{}
interface Driver extends HumanPassenger{}
In this case Driver extends HumanPassenger and Person through HumanPassenger's ancestors. You can also do this explicitly via:
interface Driver extends HumanPassenger, Person{}
The reason that I say this is more technically correct is through the "is-a" relationship that descendant classes should have. For example, a HumanPassenger is a Person, a Person is not a HumanPassenger (a person could be anything that a person could be, not just a human passenger) in dasblinkenlight's answer, a person is a passenger, but what if a person is a pedestrian...
EDIT:
Human Passenger, PetPassenger, and Driver, could all also be classes, I was just keeping it simple. example of Driver class:
class Driver extends HumanPassenger implements Person{}
or if HumanPassenger was an interface still:
class Driver implements HumanPassenger{}
or
class Driver implements HumanPassenger, Person{}
All would achieve the same things, though only the classes would be capable of instantiation of course.
Employee Class
public class Employee {
protected String name;
protected String jobsheetnumber;
public Employee(String n,String j){
this.name = n;
this.jobsheetnumber = j;
}
public Employee(String name)
{
this.name = name;
}
public String getName() {
return name;
}
public String getJobsheetnumber() {
return jobsheetnumber;
}
public void setName(String name) {
this.name = name;
}
public void setJobsheetnumber(String jobsheetnumber) {
this.jobsheetnumber = jobsheetnumber;
}
}
Mechanic Class
public class Mechanic extends Employee{
public Mechanic(String name,String jobsheetnumber){
super(name,jobsheetnumber);
}
}
Supervisor Class
public class Supervisor extends Employee{
public Supervisor(String name){
super(name);
}
}
Company Class [snippet]
public class Company {
private String companyname;
private String companyaddress;
private String postalcode;
private String city;
private String country;
private String telephonenumber;
private String faxnumber;
private String province;
private Employee supervisor;
private Employee mechanic;
public Company(String companyname,String companyaddress,String postalcode,String city,String country,String telephonenumber,String faxnumber,String province,String supervisorname,String jobsheetnumber,String mechanicname)
{
this.companyname = companyname;
this.companyaddress=companyaddress;
this.postalcode = postalcode;
this.city=city;
this.country=country;
this.telephonenumber=telephonenumber;
this.faxnumber=faxnumber;
this.province=province;
supervisor = new Supervisor(supervisorname);
mechanic = new Mechanic(mechanicname,jobsheetnumber);
}
Employee Class is the superclass of both Mechanic and Supervisor class .. right now i am using the attributes of Employee i.e name and jobsheetnumber in the subclasses Mechanic and Supervisor Class
the code works fine .. but what if i want to add extended functionality in Mechanic and Supervisor ? then i cannot access those variables because the reference is to the Employee type object.
is this the correct use Of Polymorphism ? that we have to use super() as the constructor each time we create a reference of Supervisor/Mechanic Object ?
can we not use extended functionality inside Supervisor and Mechanic Class ?
If you want to call a superclass non-zero-arg constructor then yes, you have to call it explicitly. If the superclass constructor has no arguments then the call will be inserted for you.
The point of polymorphism is so that objects can take care of themselves without having to have the rest of the program micro-manage them, so the outside program refers to them by a reference with the type of an interface or superclass without having to know the exact concrete type. For instance all employees might have a work method, where that work takes a different form for a supervisor than it does for a mechanic; the work method would be overridden by the specific subclasses, and might call the specific methods on the subclasses. So the company can iterate through all the employees and call work on each of them, while work is defined differently for different subclasses of employee.
(In practice using subclasses to describe roles is too inflexible to work, since an employee could have multiple roles, or those roles can change over time. It's usually better to use composition, here assigning Role objects to an Employee.)
A better use of polymorphism would be the same interface (methods) for different implementations. So you can decide which implementation will be used in runtime.
To explain my point i will give a example using your classes.
public class Employee{
public void work(int hours){ doNothing();}
}
public class Supervisor extends Employee{
private Object pen;
private Object note;
#Override
public void work(int hours){
observations = superviseWorkers();
note.write(observations, pen);
}
}
public class Mechanic extends Employee{
private Tool tool;
private TaskBoard taskBoard;
#Override
public void work(int hours){
task = taskBoard.getPendent()
if(task.canSolveWithTool(tool))
{
solveTask(task, tool)
}
}
}
Using example:
employees = new List<Employee>();
employees.add(new Supervisor("foo"));
employees.add(new Mechanic("bar"));
foreach(employee in employees){
//you don't need to know which kind of employee you are treating here because you are only calling a behavior that all employees have.
employee.work(8);
}
If in many places in your code you are trying to figure out which object you are dealing with probably you are doing it wrong.
I used your classes in my examples to facilitate your understanding but as Nathan Hughes suggested in this case would be better to use composition instead of inheritance.
I will handle above scenario in two ways.
Solution 1: ( Interface as roles)
You can have "state" in Employee object and you can implement role as interface.
Employee will have all common attributes & methods. You can override base class method like doWork() in respective Employee implementations.
You can add specific behaviour of Mechanic, Supvervisor with use of interfaces.
public interface ISupervise{
public void doSupervise();
}
public class Supervisor extends Employee implements ISupervise{
public void doSupervise(){
}
}
public interface IMechanic{
public void doMechanicWork();
}
public class Mechanic extends Employee implements IMechanic{
public void doMechanicWork(){
}
}
Solution 2: (Decorate role)
Implement Decorator pattern for Employee to play multiple roles. Mechanic and Supervisor will decorate Employee behaviour. Refer to this example for better understanding of Decorator pattern.
Sample code can be found #
When to Use the Decorator Pattern?
If I have a bunch of classes that all contain an Enum and EnumMap and I want to create a superclass for those classes.
public interface ColorEnum {
}
class ColorMarbles extends Toy {
enum MARBLE implements ColorEnum
{ BLUE, GREEN }
EnumMap<MARBLE, String> names = new EnumMap<MARBLE, String>(MARBLE.class);
//stuff
// fields
public void populate(ArrayList<String> designer) {
int i = 0;
for(MARBLE marble : MARBLE.values()) {
marble.name = designer.get(i);
i++;
}
}
}
class ColorBalloons extends Toy {
enum BALLOON implements ColorEnum
{ YELLOW, RED }
EnumMap<BALLOON, String> names = new EnumMap<BALLOON, String>(BALLOON.class);
//stuff
// fields
public void populate(ArrayList<String> designer) {
int i = 0;
for(BALLOON balloon : BALLOON.values()) {
balloon.name = designer.get(i);
i++;
}
}
}
How do I make create a superclass to have a generic EnumMap that contains an enum of type ColorEnum like this?
public abstract class Toy {
EnumMap<ColorEnum, String> names;
}
eidt: I realize that I was too vague with my example. Dogs are probably a bad example. I change it to something hopefully more clear.
What I have is a bunch of classes with methods like populate which populates the EnumMap. The names are in a predefined order. Instead of defining populate in every class, I'm hoping to be able to bring it to the Toy superclass so I don't have to keep copy-pasting in each new class type Toy.
Hopefully this will explain more what I'm looking for.
I have a feeling your design is needlessly overcomplicated.
With enums
If you don't require a class inheritance, you can work with enums directly as with top level classes.
public interface Animal {}
public enum Dog implements Animal {
HUSKY("Husky"), LAB("Labrador");
private final String name;
Dog(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Enums can declare fields, methods and implement interfaces like any other Java classes. Their only limitation is that their direct superclass is always java.lang.Enum and they can't be extended.
However every enum constant can have its own set of unique data passed to its constructor. It is even possible that each of the constants can override a common method of that enum with its unique implementation.
A nice tutorial explaining more about the full power of enums:
http://javarevisited.blogspot.cz/2011/08/enum-in-java-example-tutorial.html
Without enums
In case you need an actual class inheritance for sharing some common methods (for example from the Animal superclass), I still would drop the map approach and rather try something more OOP oriented:
public class Animal {
}
public abstract class Dog extends Animal {
public abstract String getName();
public static class Husky extends Dog {
#Override
public String getName() {
return "husky";
}
}
public static class Lab extends Dog {
#Override
public String getName() {
return "labrador";
}
}
}
One mechanism I have used for something like this is to extend a generic base class that has a generic parameter that allows you to pass the Enum details up to it.
This example defines a base Table class for database tables:
public class Table<Column extends Enum<? extends Column>> {
// Name of the table.
protected final String tableName;
// All of the columns in the table. This is actually an EnumSet so very efficient.
protected final Set<Column> columns;
/**
* The base interface for all Column enums.
*/
public interface Columns {
// What type does it have in the database?
public Type getType();
}
// Small list of database types.
public enum Type {
String, Number, Date;
}
public Table(String tableName,
Set<Column> columns) {
this.tableName = tableName;
this.columns = columns;
}
}
Now you can subclass this:
public class VersionTable extends Table<VersionTable.Column> {
public enum Column implements Table.Columns {
Version(Table.Type.String),
ReleaseDate(Table.Type.Date);
// Sadly all of this must be in ALL of your enums but most of the work can be pushed up to `Table`
final Table.Type type;
Column(Table.Type type) {
this.type = type;
}
#Override
public Type getType() {
return type;
}
}
public VersionTable() {
super("Versions", EnumSet.allOf(Column.class));
}
}
and make use of functionality in the parent class that handles your enum.
Note here I am passing an EnumSet to the Table constructor. I am sure you could change this to accommodate your EnumMap requirement if you decide an EnumSet is insufficient.