This question already has answers here:
Is there more to an interface than having the correct methods
(17 answers)
Closed 8 years ago.
I have an interface which is implemented by 4 different classes. Now, I want to call a setter method of one of the classes through the reference of this interface. The class is decided at run time, and the interface doesn't contain any methods or variables. So how can I set the value of private variables of one of those classes? I provide you the sample of code.
public interface InterfaceClass {
}
public class ClassOne implements InterfaceClass{
private String name;
public void setName(String name) {
this.name = name;
}
}
public class ClassTwo implements InterfaceClass {
private String name;
public void setName(String name) {
this.name = name;
}
}
class CaalingClass {
String className = "ClassOne";// the value of the string is decide at the run time
InterfaceClass i = (InterfaceClass) Class.forName(className).newInstance();
i.setName("ABC"); //this gives an error
/*
* I know it should be ((ClassOne) i).setName("ABC"); but at runtime i
* don know which class is to be called so is there any other way to
* find or it has to be done in this fashion?
*/
}
Modify your interface InterfaceClass like so,
public interface InterfaceClass {
public void setName(String name);
}
Next, modify your classes to implement InterfaceClass like so,
public class ClassOne implements InterfaceClass
public class ClassTwo implements InterfaceClass
Now your posted program should work. If not, post the full Exception. Actually, you should probably rename your InterfaceClass to something meaningful like Nameable,
public interface Nameable {
public void setName(String name);
// public String getName(); // <-- From the comments. It's not a bad suggestion.
}
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I wanted to ask if it is possible if private objects of my parent class can be inherited by my subclass through the super keyword.
I ask because I have a task for school, and I thought that private objects cannot be inherited. I also receive an error in my code and I struggle to find anything online to help me with this specifically.
For example, my parent class has:
public class Person {
private String firstName;
And then in my sub class I have:
public class Lecturer extends Person {
//....
super.firstName = firstName;
NetBeans gives me the warning that 'firstName has private access'.
You would have to do something like this
Person class:
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Subclass in separate file:
public class Employee extends Person {
public Employee(String name) {
super(name);
}
public void test() {
System.out.println("getName = " + getName()); // works
// can also do super, although it's not necessary
System.out.println("getName = " + super.getName());
}
}
If you don't want to use super.method(), but super.variable then you need to change the name variable to not be private but package-private by removing the "private" from its declaration:
public class Person {
String name;
public Person(String name) {
this.name = name;
}
}
Employee
public class Employee extends Person {
public Employee(String name) {
super(name);
}
public void test() {
System.out.println("this.name = " + name);
}
}
My previous answer used an inner class but that shouldn't be used as it would be a misuse of inner classes.
Short answer: no, they cannot be inherited.
Private variables cannot be reached from anywhere but the declaring class. This means that your super.firstName = firstName actually has 2 errors: super.firstName cannot be accessed since its private, and the firstName field does not exists from the subclass's point of view.
The only way of accessing a private variable or method directly is via reflection, and even then you have to use the setAccessible(boolean) method which might be prevented by SecurityManagers.
If you have a setter (or parameterized constructor) which accesses the private variable you can use it from an other class (due to the method being public).
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.
So I came across a very weird bug in my project. I had the following two classes
#Component
#Scope("prototype")
public abstract class World {
String name;
public World(String name) {
this.name = name;
}
final void print() {
System.out.println(name);
}
}
#Component
#Scope("prototype")
public class Hello extends World {
public Hello(String name) {
super(name);
}
}
When I instantiate an object using context.getBean(Hello.class, "foo"), I get back a Hello class bean. But when I hello.print(), it printed null.
Removing the final modifier resolved the issue. Whats going on here? Is spring having any limitations with final methods?
My assumption is that you use CGLIB proxying. You can check that by
context.getBean(Hello.class, "foo").getClass()
In that case Spring asks CGLIB to create a subclass of the Hello. That subclass gets the real instance of Hello class. This allows to override all the methods and then eventually call the target, here is how it looks approximately:
class Proxy extends Hello {
Hello target;
void print() {
target.print();
}
}
Because you marked your method as final Java doesn't allow overriding. And proxy itself (while is a subclass of Hello) doesn't get the name field initialized - it's null.
So your real Hello#print() method is not invoked - only Proxy#print() is called and Proxy#name is null, which results in null showing up in console.
So workaround I came up to is to simply move method implementation that relies on autowiring to private method which won't be proxied by CGLIB.
That would result in a given example to:
#Component
#Scope("prototype")
public abstract class World {
String name;
public World(String name) {
this.name = name;
}
final void print() {
doPrint();
}
private void doPrint() {
//name is populated here
System.out.println(name);
}
}
#Component
#Scope("prototype")
public class Hello extends World {
public Hello(String name) {
super(name);
}
}
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?
I'm having an issue that I can't find the right way to resolve by myself.
Basically I have two objects Object1 & Object2 where both of these have two properties of the same type:
public class Object1 {
...
private String name;
private String description;
...
Object1 () {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
public class Object2 {
...
private String name;
private String description;
...
Object2 () {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Now obviously I made them properties as strings here in the example but in reality they're other types.
NOTE: Object1 and Object2 are actually generated classes from XML models that I need for SOAP servces. So I can't modify them.
In some point in my code I have to access say the 'name' property of either Object1 or Object2 depending on different factors. This point is an event handler so in a certain moment of time it catches an event called with Object1 and other times with Object2.
My guess was to make a single class that would enclose both these types and expose one single "name" property and one single "description" property.
What would a standard way of doing this be?
There basically are two ways to do this:
Use a common interface that expose the getters and setters. Then let both classes implement that interface and let the handler use it.
If possible (both objects don't already extend other superclasses) you could use an abstract superclass and put the properties as well as the getters and setters there. The handler then uses that superclass.
Note that both approaches can be combined, i.e. use an interface for the handler and use an abstract superclass that implements that interface as an adapter class, i.e. you could extend that adapter when possible or just implement the interface when extending the adapter is not possible.
Example:
interface Common {
String getName();
}
abstract class CommonAdapter implements Common {
String name;
String getName() {
return name;
}
//setter as well
}
//just extend the adapter and enjoy
class Object1 extends CommonAdapter {
//specific code for Object1
}
//extending not possible, so implement the interface directly
class Object2 extends SomeOtherClass implements Common {
String name;
String getName() {
return name;
}
}
class Handler {
void handle( Common c ) {
c.getName();
...
}
}
Update:
If the classes are generated, you could create those objects as wrappers and delegate all calls to the actual class, e.g.
class Object1CommonWrapper implements Common {
Object1 delegate;
String getName() {
return delegate.getName();
}
}
make an abstract class and let both classes extend from it
Use interface or abstract class
public interface CommonObject {
//gettter and setter
}
public Class Object1 implements CommonObject { ... }
public Class Object2 implements CommonObject { ... }
public Class MainClass {
public void someMethod() {
if(someCondition) {
CommonObject obj1 = new Object1();
//use obj1
} else {
CommonObject obj2 = new Object1();
//use obj2
}
}
}
Use factory pattern
it depends a bit on the behaviour of said methods. So if:
Both Object1/ Object2 have the absolut identical code for those methods i would go with inheritance, have a superclass that defines those fields/ methods and the two objects extend it.
Both Object1/ object2 must have the same method signature but have to handle the internal logic in different ways i would go with a interface defining the method signature that both Object1/2 must implement.
You can define an interface that both Object1 and Object2 implement. The interface would include the methods that you need to call, but each class can implement them in its own way.
For example, it might look something like this:
public interface Describable {
String getName();
String getDescription();
}
public class Object1 implements Describable {
... implements the methods in some way
}
public class Object2 implements Describable {
... implements the methods in another way
}
With that, whatever code needs to deal with both of these types of objects can refer to them as Describable and take advantage of polymorphism. For example:
Describable eventObject = ...get the object...
eventObject.getName();
eventObject.getDescription();
Or even something like:
public void handle(Describable describable) {
describable.getDescription();
... more stuff...
}
That code doesn't know (or care) what type of object is actually passed in to the method, only that it can interact with it as a Describable.
This is a common idiom in Java and OO design in general. The core libraries use it all over the place.
By the way, inheritance (ie, using a common base super class) is another option. Just be aware that the technique of implementation inheritance has some trade-offs and is often abused/misused. For example see this discussion.