Reputation: 121
I have implemented in such a way below where the class object would be returned and with that I'd be calling the required methods and get the output. To my knowledge, it was appropriate to use. I have recently come across post that suggests that it is bad practice. geeksforgeeks - Post
And I'm looking for an alternate way to implement it.
Main Class:
public class PolymorphismExample {
public static void main(String[] args) {
System.out.println("Enter the Role details");
Scanner scan = new Scanner(System.in);
String role = scan.nextLine();
System.out.println((Object)role.getClass().getSimpleName());
RolesandResponsibilities rr = getRoleLoc(role);
assert rr != null;
System.out.println("Role: " + rr.getRole());
System.out.println("Responsibility: " + rr.getResponsibility());
scan.close();
}
public static RolesandResponsibilities getRoleLoc(String role) {
switch (role) {
case "tester":
return new tester("tester");
case "developer":
return new developer("developer");
case "scrummaster":
return new scrummaster("scrummaster");
case "projectmanager":
return new projectmanager("projectmanager");
case "intern":
return new intern("intern");
default:
return null;
}
}
}
Super Class:
class RolesandResponsibilities {
String role;
public RolesandResponsibilities (String role) {
this.role = role;
}
public String getRole() {
return role;
}
public String getResponsibility() {
return "No responsibility specified";
}
}
Inherited Sub-Classes:
class developer extends RolesandResponsibilities {
public developer(String role) {
super(role);
}
public String getResponsibility() {
return "Develop the application";
}
}
//Just added only one class as the post is getting lengthy.
Upvotes: 1
Views: 1241
Reputation: 51445
I prefer magicmn's answer, but I thought I'd illustrate what I said in the comment. As it turns out, I only need to implement one concrete class.
I ran the following test:
Enter the role:
developer
Role: developer
Responsibility: Develop the application
I created a RolesAndResponsibilities
interface. I created a ConcreteClass
class based on the interface. I couldn't come up with a better name for the concrete class. I could have stuck an I in front of RolesAndResponsibilities
to create the interface name. I see why that's a standard in some Java shops.
I created a createRoleList
method to create a java.util.List
role list.
The main
method became pretty simple after that.
Here's the complete runnable code. I made the additional class and interface inner classes so I could post the code in one block.
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class PolymorphismExample {
public static void main(String[] args) {
PolymorphismExample pe = new PolymorphismExample();
List<RolesAndResponsibilities> roleList = pe.createRoleList();
Scanner scan = new Scanner(System.in);
System.out.println("Enter the role: ");
String role = scan.nextLine();
for (RolesAndResponsibilities rr : roleList) {
if (rr.isRole(role)) {
System.out.println("Role: " + rr.getRole());
System.out.println("Responsibility: " +
rr.getResponsibility());
break;
}
}
scan.close();
}
public List<RolesAndResponsibilities> createRoleList() {
List<RolesAndResponsibilities> roleList = new ArrayList<>();
RolesAndResponsibilities rr = new ConcreteClass("developer",
"Develop the application");
roleList.add(rr);
rr = new ConcreteClass("tester", "Tests the application");
roleList.add(rr);
// The rest of the roles go here;
return roleList;
}
public class ConcreteClass implements RolesAndResponsibilities {
private final String role, responsibility;
public ConcreteClass(String role, String responsibility) {
this.role = role;
this.responsibility = responsibility;
}
@Override
public boolean isRole(String role) {
return (this.role.equalsIgnoreCase(role));
}
@Override
public String getRole() {
return role;
}
@Override
public String getResponsibility() {
return responsibility;
}
}
public interface RolesAndResponsibilities {
public boolean isRole(String role);
public String getRole();
public String getResponsibility();
}
}
Upvotes: 0
Reputation: 1914
Instead of switch-case you can create a static map. Is that a better solution? It depends.
private static Map<String, RolesandResponsibilities> roles = Arrays.asList(new developer("developer")) // rest of your roles
.stream()
.collect(Collectors.toMap(r -> r.getRole(), r -> r));
public static RolesandResponsibilities getRoleLoc(String role) {
return roles.get(role);
}
But I think you're example has a much bigger problem. What exactly qualifies developer
, tester
, scrummaster
, projectmanager
and intern
to be their own classes? A class should be the blueprint for objects, what you are doing is creating more blueprints for the things that should be objects.
I would fix this by adjusting RolesAndResposibilities
.
public class RolesandResponsibilities {
private String role;
private String responsibility;
public RolesandResponsibilities(String role, String responsibility) {
this.role = role;
this.responsibility = responsibility;
}
//getter
}
And then just create the objects and add them to a collection.
RolesandResponsibilities none = new RolesandResponsibilities("", "No responsibility specified");
RolesandResponsibilities developer = new RolesandResponsibilities("developer", "Develop the application");
List<RolesandResponsibilities> roles = Arrays.asList(none, developer);
Map<String, RolesandResponsibilities> rolesMap = roles.stream().collect(Collectors.toMap(r -> r.getRole(), r -> r));
Or if you know your roles will not change you can turn RolesandResposibilities
into an enum.
public enum RolesandResponsibilities {
NONE("", "No responsibility specified"), DEVELOPER("developer", "Develop the application");
private String role;
private String responsibility;
RolesandResponsibilities(String role, String responsibility) {
this.role = role;
this.responsibility = responsibility;
}
public String getRole() {
return role;
}
public String getResponsibility() {
return responsibility;
}
}
List<RolesandResponsibilities> roles = Arrays.asList(RolesandResponsibilities.values());
Upvotes: 1
Reputation: 718788
To my knowledge, it was appropriate to use.
It isn't. Two reasons:
If you use the same name for a class and a method, it is liable to confuse the reader. For example:
public class Test {
public Test() { ... }
public void Test() { ... }
}
The reader is liable to misread the Test
constructor as a method and vice versa, leading to an incorrect reading of the code in general.
Even if they do correctly spot the subtle difference, they are liable to be unsure of your intentions. They will question if you made a mistake in writing the code and accidentally declared a method where you meant to declare a constructor. Or vice versa. Even if they come to the conclusion that this is not a mistake, they will have wasted their time working it out.
This is a violation of accepted Java style rules ... which are designed to avoid the above confusion.
If a class and method name are the same, then one of them violates the style rules.
The fact that your code is accepted by your IDE and a Java compiler is immaterial. Proper code doesn't just need to work. It also needs to be readable.
Now, you are free to make up your own mind about this, but if you choose to ignore style, expect to get a lot of negative feedback from people who have to read your code.
Upvotes: 3