Decide at runtime which class to invoke - java

Interface :
public interface Person {
public String name = "";
}
I have two classes:
public class Male implements Person {
public String name = "Male1";
}
Another class being
public class Female implements Person {
public String name = "Female";
}
I want to instantiate a class at runtime depending on who the user is. Something like :
Person p = getPerson("M");
System.out.println("P = " + p.name);
private static Person getPerson(String gender) {
if (gender.equals("M"))
return new Male();
else if (gender.equals("F"))
return new Female();
else
return null;
}
I am expecting the output to be: Male1
How can I achieve this ? What is the best design pattern to achieve this functionality ?

lookup and use Class.forName()

You don't put attributes in an interface.
Your interface should include a String getName(); method signature. Then you implement this method in all inherited classes. That way, you can call getName() on your Person object to retrieve the person's name regardless of the implementation class.
To instantiate, take a look at the Factory pattern.

There are several options, but you could use Abstract Factory:
Create a PersonFactory interface with just a createPerson method. Then make two implementations:
MaleFactory which returns a new Male
FemaleFactory which returns a new Female
Then keep a Map<String, PersonFactory> where the key is the gender and the value is an instance of the factory that will create the appropriate Person instances.
Getting a new Person given the gender becomes as simple as
map.get(gender).createPerson()
EDIT:
I see you have edited your question so that it now includes a question about using variables in interfaces.
Basically, you don't want to put the variable in the interface, because that will mean it's static (the static keyword is implied in this case since interfaces can't have non-static variables), and I guess you don't want all persons to have the same name.
So you'll have to declare a getName() method in the interface. If the behaviour should be the same for all genders (I don't see why not) then you can just put both the name variable and the getName() method in an abstract base class (e.g. AbstractPerson) which both Male and Female extend.

Related

Is it possible to receive subclass's name in compile time in Java?

I'm trying to create a snacks machine implementation in java.
I have created an abstract class named Product that will give the basic design for each of the offered products.
I mean we have the abstract class Product and then other classes like Nachos, Cake, etc.. that inherita from Product.
Product class does not contain too much, it just contains the name , the price and the available amount of the product (these are the fields in the class).
It also has get methods for the fields that just return the value for each one.
The problem is that I want to set the name of the product as a static final because if a product's name is Nachos, it won't be changed. I mean it'll be possible to create more Nachos objects but the name of their class is still going to be Nachos.
So there is no reason to NOT to do that static final.
The issue with that is that i'm not sure how to set it correctly.
public abstract class Product {
private static final String productName = getClass().getSimpleName();
private int price;
private int amount;
....
Constructor..
Get methods..
I thought about getClass().getName() or getSimpleName() but it gives me an IDE error which indicates that the only way for me to also use that field as static final and also to use getClass is by writing Product.class.getName();.
The problem is that if i'll do that, the name that will be returned is Product and not Cake or Nachos or other sub classes.
If your Class has some attribute that describes that Class (e.g a product name), that's an attribute of that Class. You shouldn't write code that uses the name of the class itself with getClass().getName(), that's tying your business logic to implementation details, and there's no reason (or very few good reasons), why your code would need to know the name of the class itself.
Instead, add an attribute like productName to your class:
public class Product{
private String productName;
public Product(String name){
this.productName = name;
}
public String getProductName(){
return this.productName;
}
}
You should just use "final" and drop the "static". By declaring the variable as final you can assign the value of "getClass" that use "this" for reference. "this" doesn't work for static.
abstract class Product {
private final String productName = this.getClass().getSimpleName();
public String getProductName() {
return productName;
}
}
The "this" can be omitted in "this.getClass().getSimpleName()", leaving only "getClass().getSimpleName().
It doesn't make sense to use "static" because you would access the attribute directly via the class reference. But this would not work because to get the "getClass" you would need to be within some scope (constructor...) because the attribute is static, it is impossible to assign the value of the attribute at the time of its creation, making it impossible to use the " Final".
A static member belongs to the class in which it is defined. Declaring productName as static on the class Product means that every concrete implementation would have the same value. This is not what you want.
I think the solution that is closest to what you describe is not to have a member at all. Instead, declare an accessor as follows.
public abstract class Product {
public final String getProductName() {
return getClass().getSimpleName();
}
}
Thus, every instance of a given subclass (e.g. Taco) references the same Class object for its type. We never duplicate the value because we are accessing the singular value in our memory space. We declare this method to be final so that subclasses cannot override it. This enforces that the productName will always be the simpleName of the concrete implementation.

Confusion with Java inner private classes and toString()

I have a project where I must use inner classes to declare types of food (created as 'Item' objects); for example, Pancake:
private class Pancake {
Item pan = new Item(5.50);
public String toString() {
}
}
As shown above the assignment given to me says each private inner class must override toString to return the name and price of the object. But, the test cases read what is returned from the toString method in the Item class (a different public class), which I currently have coded as:
#Override public String toString() {
return "" + " ($" + this.price + ")";
}
I do not know how to pass this toString method the name of the food type (i.e, Pancake). Item objects are created with a constructor that asssigns them a price, and that is all that is allowed. So I cannot use this.name or something like that to access the name of the food. How can I give this toString() method the name of the food (the private inner class, in a different class entirely)? No constructors are allowed to be implemented in the private classes. I've tried using this.getClass() but all that does is return a class type of Item, not the specific food class. Any help would be appreciated.

Java factory pattern, creating specific classes

I had a question on an interview where I had 2 types of foods, say bread and cake, was given the following:
public class FoodFactory{};
public class Food{};
public static void main(String[] args) {
Food foo = FoodFactory.get("bread");
System.out.println(foo.getClass().getName());
}
Given the FoodFactory class and Food class, I wasn't sure how to make this work so that it would print out "bread" for the class. It really seemed like the only way to have gotten it to print bread was to create a Bread class and have the FoodFactory return that.
I'm just wondering if I'm missing anything, because FoodFactory and Food were classes given so I assumed those were the only 2 classes I needed to change. Is there a way to have implemented the two classes given and made it print "bread" while using just those 2 classes?
So one way to do it would be to make a class Bread which extends class Food and have the FoodFactory.get() return the appropriate object based on the string passed.
class Food {};
class Bread extends Food {};
class FoodFactory {
public static Food get(String type){
switch(type){
case "bread" : return new Bread();
default : return new Food();
}
}
}
Another way to do it would be to use reflection.
Unless you compile a new class at runtime (which is possible, but inappropriate here), you will of course need to add a class if you want to return a Bread instance.
Ideally, Food should turn into an interface or an abstract class at best. Then you have classes Bread and Cake implement/extend Food. Your FoodFactory has a static method get that accepts the food as a String. Depending on the value, you instantiate and return one of the concrete classes which will give you what you need when you print class name.
I think that the real question the interviewer was asking was if you understand the pattern and polymorphism. As noted in one of the comments getClass().getName() won't return 'Bread' unless there really is a Bread class. What you could have done was to the suggest the interviewer that Food is the base class which in this case should be extended by Cake and Bread classes, or even propose to change it to abstract class or interface. Then you could have proposed a simple factory class which would create the required implementation 'hidden' behind the base class interface.
Your problem is basically an example for the Java Factory Design Pattern.
Assumed you have a project, respectively a class hierarchy with multiple Interfaces and different classes, what would be the easiest way to create any class? This is where a Factory comes in place to handle all operations regarding class instance creation.
Now to your case, the convenient way would be to change your Class Food to an interface eg:
public interface Food {
String getType();
}
Now you need your Cake and Bread classes, which implement the interface Food
public class Cake implements Food{
#Override
public String getType() {
return "Cake";
}
}
public class Bread implements Food{
#Override
public String getType() {
return "Bread";
}
}
Now you need to define your FoodFactory class which has a static getmethod, that returns a Food depending on the criteria that has been supplied.
public class FoodFactory {
public static Food get(String classifier){
if(classifier.equals("Cake")) return new Cake();
if(classifier.equals("Bread")) return new Bread();
//no matching Food to create
throw new IllegalArgumentException("The " + classifier + " is not a valid classifier");
}
}
Once you have your Factory you can use it for any creation operation.
If you want to print out Bread from a Food instance, you can achieve this like this:
//food is now an instanceof Bread
Food food = FoodFactory.get("Bread");
System.out.println(food.getType());
Which simply just prints
Bread
Further:
To make sure every creation is handled only by the FoodFactory you should make every constructor of your Food classes protected

Why to override a superclass and call it again inside the function?

I am reading a code which is done something like this, and I want to understand why it is doing this:
public abstract class Class2 extends Class1 {
...
#Override
public ObjectType someFunction() {
ObjectType var = super.someFunction();
....
return var;
}
}
So the someFunction() method has been overwritten and the someFunction() of the parent is called again inside it.
Does it make sense to you? What would be the motivation for doing this?
If you don't want to duplicate the code for the entire overridden method, but you want to change the logic a little bit or if you want to add a little bit of code, then you can call the overridden method and provide additional code.
This prevents duplication of code and logic in subclasses that wish to override a method but retain some behavior.
As yshavit has indicated in a comment, calling the overridden method may be the only way to access data that is private in the superclass.
Pretty usefull when you want to use inheritance properly.
Just imagine that you have a class Person which is composed by a name and a surname and you want to specify the job, like Farmer.
class Person {
private String name;
private String surname;
//... Constructor
public String getInfos() {
return this.name + " " + this.surname;
}
}
class Farmer extends Person {
//... Constructor
#Override
public String getInfos() {
return super.getInfos() + " is a farmer.";
}
}
Person p1 = new Person("Name", "Surname");
System.out.println(p1.getInfos());
// Show "name surname"
Person p2 = new Farmer("Name", "Surname");
System.out.println(p2.getInfos());
// Show "name surname is a farmer."

Inherited enum redefinition

It is more complex than it sounds, but I think I am obliged to try something like it. I want to make an abstract parent class with a prototyping of an enum (I want to declare the enum with only one value probably that will be the default unitialized one and also declaring a couple of methods that I will be using from the subclass), then I want to class that will extend the abstract parent to actually intialize the very same enum (I know that this practically hides the parent enum) so that the kid class will define a set of items inside the enum, but keep the methods probably.
I do not know much about this level of abstraction so I will now describe the nature of my problem, in case there is a more practical solution:
I have a bunch of files that contain classes that implement a lot of commands based on enums. (e.g. class1 implements Observer has an update method that uses an enum-based switch to decide what command was picked, same applies for the other classes) I now want to abstract this whole thing in a way that I have an enum variable with the exact same name in all classes (e.g. CommandSet) so that I can have a generic method inside the parent that will be able to print a help list to my system using the inside methods of the enum. Now I know I can rewrite the exact same method in every class, but I want to abstract it so that others can keep on extending the library I am making!
Hopefully I am not too confusing or too confused and somone can help me! :)
Edit: Here is an idea of the code (Probably not right):
public abstract class Commands{
enum CommandSet{
// empty command, placeholder
null_command ("command name", "command description");
// the Strings used for name and description
private final String name;
private final String description;
// constructor
CommandSet(String name, String description){
this.name=name;
this.description=description;
}
// get parameters
public String getName(){
return name;
}
public String getDescription(){
return description;
}
}
public void showHelp(){
for (CommandSet i : CommandSet.values()) {
printf(i.getName(),":",i.getDescription());
}
}
}
public class StandardCommads extends Commands implements Observer{
// I want to change the enum here, just changing the values so that null_command ("command name", "command description") will get removed and I will add a dozen other values, but keep the methods that the parent had
// update inherited from Observer
#Override
public void update(Observable observable, Object object) {
// I want the commands inside the switch cases defined inside this class's enum
switch(CommandSet.valueOf(String.valueOf(object)){
case command1: doStuff1();break;
case command2: doStuff2();break;
...
case commandN: doStuffN();break;
}
// other methods
void doStuff1(){
...
}
...
void doStuffN(){
...
}
}
public class NonStandardCommads extends Commands implements Observer{
// Another set of commands here for the enum keeping the same methods it had in the parent
// update inherited from Observer
#Override
public void update(Observable observable, Object object) {
// Other set of commands inside this class used in the switch statement
switch(CommandSet.valueOf(String.valueOf(object)){
case Zcommand1: doStuffz1();break;
case Zcommand2: doStuffz2();break;
...
case ZcommandN: doStuffzN();break;
}
// other methods
void doStuffz1(){
...
}
...
void doStuffzN(){
...
}
}
Impossible: Java enums can neither extend another class nor be extended themselves.
They can however implement interfaces. Perhaps you can use that to your advantage.
There is something else about enums that may help you: enums are not immutable. You could change field values of the enums, however that would change them for the whole JVM.
Another approach maybe to pass your subclass instances into a method of the enum and have the enum use your subclass as a call back to get different functionality out of an enum for a different user of the enum.
Nope, you can't do that.
Java Enums run out of gas very quickly & definitely, when you want to add/extend more definitions or instantiate the enum instances, at a later time. (eg load them from database, configure them in an instance method, not just statically.)
Behaviour/ or logic in Java enums is kinda limited too -- you can define & set properties, but only what's statically initializable, and logic seems basic (you end up mainly just comparing references or ordinals, with the other defined enum constants).
What you can do:
You can implement an ancestor Command or AbstractCommand class, with a integer Code, and then subclass it to define concrete values/ additional codes/ load or configure instances, etc.
For further benefit, you get efficient switch & despatch (by Code) plus the ability to define further details/properties, instantiate commands as-needed, etc.
Essentially, this is how you used to define an Enum before Java supported them. Though you may be using them as value objects, rather than strictly static.
My expertise:
I've done extensive compiler & type-system work, tried enums for file-types and associated data/behaviour.. explored the outer limits, and reached the definite boundaries.
I also like being able to instantiate & return a new UnknownFileType("") as an answer, too. Enums can't do that.
Example:
(We'll despatch by String, not int -- since your code appears to be using Java 7. This makes command resolution easier, than requiring both a syntactical "name" and an internal integer "code".)
public static class Command {
protected String code;
protected String desc;
public String getCode() {return code;}
public String getDesc() {return desc;}
public Command (String code, String desc) {
this.code = code;
this.desc = desc;
}
public String toString() {return code;}
}
public class StandardCommands {
public static Command READ = new Command("READ", "read a record");
public static Command CREATE = new Command("WRITE", "create a record");
public static Command EDIT = new Command("WRITE", "modify a record");
}
public class FurtherCommands extends StandardCommands {
public static Command LIST = new Command("LIST", "list all records");
}
public class QueryCommands extends FurtherCommands {
public static class QueryCmd extends Command {
protected String search;
public String getSearch() {return search;}
// constructor..
}
public static QueryCmd QUERY_EXAMPLE = new QueryCmd("QUERY", "example", "query for specified string");
public static QueryCmd createQuery (String search) {
return new QueryCmd( "QUERY", search, "query for specified string");
}
}

Categories