I have some strange question.
I have an interface in java:
public interface Inventory{
public void add(// take an object of a class);
public int delete(// take an object of a class);
public int edit(// take an object of a class);
}
then i wrote a class that implements the interface.
public class Supply implements Inventory{
public void add( // object of some class) {}
public int edit( // object of some class) {}
public int delete( // object of some class) {}
}
then i wrote another class that implements the interface but with different object name in parentheses.
public class support implements Inventory{
public void add(// object of different class) {}
public int edit(// object of different class) {}
public int delete(// object of different class) {}
}
my question is: what is the parameter that must be written in interface methods in order to make the other classes take any object name that would like to implement in its own way.
That is what generics are for. You can have an interface Inventory<T> with a method void add(T t). Then you can have a class that implements Inventory<Product> with a method add(Product p) but you could also have a class that implements Inventory<Supplier> with a method void add(Supplier s).
Related
In my project I have a superclass and two subclasses extending from it. There is a method in the superclass that is overriden differently in each subclass.
I want to know if it's possible to introduce a method (in another class) that takes object of either subclass as a parameter and calls a method overriden in one of subclasses (depending on to which subclass does the object belong).
public class Superclass{
public int method(){return 0;}
}
public class Subclass1 extends Superclass{
public int method(){return 1;}
}
public class Subclass2 extends Superclass{
public int method(){return 2;}
}
public class CallingClass{
public static int dependantCall(Superclass parameter){return parameter.method}
I want to be able to do something like
Subclass1 subclassObject = new Subclass1;
System.out.println(CallingClass.dependantCall(subclassObject));
and get output
1
That is what Polymorphism is for! Defining the Superclass as a parameter type will allow you to pass either subclass in.
For example in your other class you can define it like this:
// classes Dog and Cat extend Animal and override makeNoise()
class Owner{
playWith(Animal a){
a.makeNoise();
}
}
Now the Owner can accept owner.makeNoise(cat) and owner.makeNoise(dog)
More reading: https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html
Yes, it is entirely possible. Here's how that method would look like:
public <T extends Superclass> void foo(T subclassObject) {
...
}
Or:
public void foo(Superclass obj) {
...
}
Note that in the above method, you can pass subclasses' objects as well (they are covariant data types).
This is what Java does by default when you create subclases, so no need to do anything special. Each object carries it's type information at run time, and the method invoked would always be the most specific one for the object. Example:
public class Doer {
public void doSomething() {
// Body presence
};
}
public class Painter extends Doer {
#Override
public void doSomething() {
// Paint here
}
}
public class Manager extends Doer {
#Override
public void doSomething() {
// Micromanage here
}
}
// Elsewhere in your code:
public void busyness(Doer doer) {
doer.doSomething();
}
A style note: if it is possible, one should prefer using interfaces instead of base classes (base classes those should be used only if you want to share implementation between subclasses). Example with interfaces:
public interface Doer {
void doSomething();
}
public class JackOfAllTrades implements Does {
#Override
public void doSomething() {
// Do whatever necessary
}
}
// Client code stays exactly the same as above:
public void busyness(Doer doer) {
doer.doSomething();
}
Note that in Java a class can have only one base class but can implement multiple interfaces.
#Override annotations are not strictly required, but they help Java compiler to spot some errors for you (e.g. if you misprint method name).
In your example it would look like
public class CallingClass {
public static int dependantCall(Superclass parameter) {
return parameter.method();
}
}
Subclass1 subclassObject = new Subclass1();
System.out.println(CallingClass.dependantCall(subclassObject));
The program has the next code:
public class RxTaskHandler<T> implements OnSuccessListener<T>{
public RxTaskHandler(MaybeEmitter<T> emitter){
this.emitter = emitter;
}
public static void assignTask(MaybeEmitter<T> emitter){
RxTaskHandler rxTaskHandler = new RxTaskHandler(emitter);
task.addOnSuccessListenerr(rxTaskHandler);
}
#Override
public void onSuccess(Object o) {
emitter.onNext();
}
}
The question about this line - task.addOnSuccessListenerr(rxTaskHandler). We must add OnSuccessListener interface, but instead of this we add the instance of the class which implements OnSuccessListener. It means we can replace instance of the class (implements necessary interface) by instance of the interface?
Yes,
It follows the rule of inheretance.
Here interface acts as parent class and class which implements interface acts as child class.
I have an abstract class that should implement a public field, this field is an interface or another abstract classe.
something like this:
public abstract class GenericContainer {
public GenericChild child;
}
public abstract class GenericChild {
public int prop1=1;
}
public abstract class SpecialChild extends GenericChild {
public int prop1=2;
}
Now i have another specialized class Container:
public abstract class SpecialContainer extends GenericContainer {
public SpecialChild child=new SpecialChild(); //PAY ATTENTION HERE!
}
Java allow me to compile this, and i IMAGINE that the field child in SpecialContainer is automatically overloading the field child of the GenericContainer...
The questions are:
Am i right on this? The automatic 'overloading' of child will happen?
And, more important question, if i have another class like this:
public class ExternalClass {
public GenericContainer container=new SpecialContainer();
public int test() {
return container.child.prop1
}
}
test() will return 1 or 2? i mean the GenericContainer container field what prop1 will call, the generic or the special?
And what if the special prop1 was declared as String (yes java allow me to compile also in this case)?
Thanks!
In Java, data members/attributes are not polymorphic. Overloading means that a field will have a different value depending from which class it's accessed. The field in the subclass will hide the field in the super-class, but both exists. The fields are invoked based on reference types, while methods are used of actual object. You can try it yourself.
It's called, variable hiding/shadowing, for more details look on here
It isn't overriding anything, you're just hiding the original field at the current class scope. If you use a variable with the subtype you will still be able to access the original property. Example:
abstract class GenericContainer {
public GenericChild child;
}
abstract class GenericChild {
public int prop1=1 ;
}
class SpecialChild extends GenericChild {
public int prop1=2;
}
class SpecialContainer extends GenericContainer {
public SpecialChild child;
}
public class Main {
public static void main( String ... args ) {
GenericContainer container = new SpecialContainer();
container.child = new SpecialChild();
System.out.println( container.child.prop1 );
SpecialChild child = (SpecialChild) container.child;
System.out.println( child.prop1 );
}
}
This prints 1 and then 2.
From SpecialChild you would also be able to go up one level using super:
class SpecialChild extends GenericChild {
public int prop1=2;
public int getOriginalProp1() {
return super.prop1;
}
}
Regarding
....and i IMAGINE that the field "child" in SpecialContainer is automatically overloading the field 'child' of the GenericContainer...
No. Fields don't get overridden, only methods do.
This is one reason why use of (overridable) getter and setter methods are preferred to direct access to fields. Your fields should almost all be private.
As for your design, there's no need for your SpecialContainer class to have a SpecialChild field, but instead the SpecialChild object should be placed in the GenericChild field.
Why nobody is observing that program will throw NullPointerException.
subclass's field with same name will hide super class's field. There is no overriding with field. Overriding is only possible with methods.
Original Code by Author:
public abstract class GenericContainer {
public GenericChild child;
}
public abstract class GenericChild {
public int prop1=1;
}
public abstract class SpecialChild extend GenericChild {
public int prop1=2;
}
public abstract class SpecialContainer extends GenericContainer {
public SpecialChild child=new SpecialChild(); //PAY ATTENTION HERE!
}
public class ExternalClass {
public GenericContainer container=new SpecialContainer();
public int test() {
return container.child.prop1
}
}
Java allow me to compile this, and i IMAGINE that the field "child" in
SpecialContainer is automatically overloading the field 'child' of the
GenericContainer...
Firstly, Inheritence doesn't apply to variables. Fields(Insatnce variables) are not overridden in your sub-class.they are only visible in your subclass if they are marked with either public, protected or default.
To answer your question it maintains both instances. And depending on how you refer to the container (either through the abstract or the impl) determines which variable you are referring to.
public class Test {
public abstract class Container{
public Generic gen = new Generic();
}
public class ContainerImpl extends Container{
public GenericImpl gen = new GenericImpl();
}
public class Generic{
public int prop = 0;
}
public class GenericImpl extends Generic{
public int prop = 1;
}
public Test(){
Container c = new ContainerImpl();
System.out.println(c.gen.prop); // Outputs "0"
System.out.println(((ContainerImpl)c).gen.prop); // Output "1"
}
public static void main(String[] args) {
new Test();
}
}
The bigger question at hand is, why would you design something like this? I'm assuming you are asking from a theoretical perspective.
My 2 cents, this isn't great OO design. You would be better off making the public variables private and assigning their values through a constructor or property setter. As-is, it will lead to unexpected results in your code.
How do I create an object of an abstract class and interface? I know we can't instantiate an object of an abstract class directly.
You can not instantiate an abstract class or an interface - you can instantiate one of their subclasses/implementers.
Examples of such a thing are typical in the use of Java Collections.
List<String> stringList = new ArrayList<String>();
You are using the interface type List<T> as the type, but the instance itself is an ArrayList<T>.
To create object of an abstract class just use new just like creating objects of other non abstract classes with just one small difference, as follows:
package com.my.test;
public abstract class MyAbstractClass {
private String name;
public MyAbstractClass(String name)
{
this.name = name;
}
public String getName(){
return this.name;
}
}
package com.my.test;
public class MyTestClass {
public static void main(String [] args)
{
MyAbstractClass ABC = new MyAbstractClass("name") {
};
System.out.println(ABC.getName());
}
}
In the same way You can create an object of interface type, just as follows:
package com.my.test;
public interface MyInterface {
void doSome();
public abstract void go();
}
package com.my.test;
public class MyTestClass {
public static void main(String [] args)
{
MyInterface myInterface = new MyInterface() {
#Override
public void go() {
System.out.println("Go ...");
}
#Override
public void doSome() {
System.out.println("Do ...");
}
};
myInterface.doSome();
myInterface.go();
}
}
There are two ways you can achieve this.
1) Either you extend / implement the Abstract class / interface in a new class, create the object of this new class and then use this object as per your need.
2) The Compiler allows you to create anonymous objects of the interfaces in your code.
For eg. ( new Runnable() { ... } );
Hope this helps.
Regards,
Mahendra Liya.
You can provide an implementation as an anonymous class:
new SomeInterface() {
public void foo(){
// an implementation of an interface method
}
};
Likewise, an anonymous class can extend a parent class instead of implementing an interface (but it can't do both).
public abstract class Foo { public abstract void foo(); }
public interface Bar { public void bar(); }
public class Winner extends Foo implements Bar {
#Override public void foo() { }
#Override public void bar() { }
}
new Winner(); // OK
"instantiate" means "create an object of".
So you can't create one directly.
The purpose of interfaces and abstract classes is to describe the behaviour of some concrete class that implements the interface or extends the abstract class.
A class that implements an interface can be used by other code that only knows about the interface, which helps you to separate responsibilities, and be clear about what you want from the object. (The calling code will only know that the object can do anything specified in the interface; it will not know about any other methods it has.)
If you are using someone else's code that expects a Fooable (where that is the name of some interface), you are not really being asked for an object of some Fooable class (because there isn't really such a class). You are only being asked for an instance of some class that implements Fooable, i.e. which declares that it can do all the things in that interface. In short, something that "can be Foo'd".
You write a class that derives from the abstract class or implements the interface, and then instantiate that.
What you know is correct. You cannot create an object of abstract class or interface since they are incomplete class (interface is not even considered as a class.)
What you can do is to implement a subclass of abstract class which, of course, must not be abstract. For interface, you must create a class which implement the interface and implement bodies of interface methods.
Here are orginal tutorial on oracle site, http://download.oracle.com/javase/tutorial/java/IandI/abstract.html and http://download.oracle.com/javase/tutorial/java/concepts/interface.html
You can not instantiate the abstract class or an interface, but you can instantiate one of their subclasses/implementers.
You can't instantiate an abstract class or an interface, you can only instantiate one of their derived classes.
In your example
MyAbstractClass ABC = new MyAbstractClass("name") {
};
You are instantiating any class that implements Suprising.
public abstract class AbstractClass { ... }
public interface InterfaceClass { ... }
// This is the concrete class that extends the abstract class above and
// implements the interface above. You will have to make sure that you implement
// any abstract methods from the AbstractClass and implement all method definitions
// from the InterfaceClass
public class Foo extends AbstractClass implements InterfaceClass { ... }
NO, we can't create object out of an interface or Abstract class because
Main intention of creating an object is to utilize the wrapped methods and data.
As interface don't have any concrete implementation hence we cannot.
For abstract class we may have concrete method or abstract method or both.
There is no way for the API developer to restrict the use of the method thats don't have implementation.
Hope help.
No, you are not creating the instance of your abstract class here. Rather you are creating an instance of an anonymous subclass of your abstract class. And then you are invoking the method on your abstract class reference pointing to subclass object.
I've been fighting with trying to override a method in a generic abstract class.
public abstract class Grandparent<T extends Grandparent>
public T set(final T other) //does stuff I don't want to do
public abstract class Parent<T extends Parent<T>> extends Grandparent<T>
public T set(final Parent<?> other) // does stuff I want to do
All the child classes extend Parent<child>.
However, I can't call the set() function I want by just constructing one of the child classes.
Child_1 test = new Child_1();
Child_1 test_2 = new Child_1();
test.set(test_2) //this calls the function I don't want
Parent<Child_1> test_3 = new Child_1();
Parent<Child_1> test_4 = new Child_1();
test3.set(test_4) //this calls the function I do want
This requires modification of already-existing code, however. A lot of it. I don't want to rewrite the set method to
public T set(T other)
because then I'll lose the ability to set one child class object from a different child class object.
How can I write the set() method to trigger any time a child object calls it, passing in any other child object, without any modifications to outside code?
To override a method, you need provide an override-equivalent signature, which implies that the method name and number and types of arguments must be equal. This is not the case For Grandparent.set() and Parent.set(). Consequently, Parent.set() overloads, rather than overrides, Grandparent.set().
The simplest solution I see is to generalize the method signatures as follows:
public abstract class Grandparent<T extends Grandparent>
public T set(Grandparent<?> other)
public abstract class Parent<T extends Parent<T>> extends Grandparent<T>
public T set(Grandparent<?> other)
That way, the methods override, and you don't have to modify any child classes.
Subsequent comments helped to clarify what you are after, but I may still be baffled. Perhaps this will help; if not, please try to elaborate on your question.
public abstract class Grandparent<T extends Grandparent<T, Q>, Q extends Grandparent<T, Q>>
{
public abstract Q set(Q other);
}
class Parent<T extends Parent<T>>
extends Grandparent<T, Parent<T>>
{
#Override
public Parent<T> set(Parent<T> other)
{
throw new UnsupportedOperationException("set");
}
}
How can I write the set() method to
trigger any time a child object calls
it, passing in any other child object,
without any modifications to outside
code?
Can you include code modeling what you want to do - I just want to be clear what it is you want because at the moment I suspect it simply is not allowed - no matter what you do.
EDIT
Classes I used to test with...
package test.stack.overflow;
public abstract class GrandParent<T extends GrandParent>
{
public T set(final GrandParent<?> other)
{
System.out.println("GrandParent.set=" + other);
return null;
}
}
public abstract class Parent<T extends Parent<T>> extends GrandParent<T>
{
public Parent<?> set(final Parent<?> other)
{
System.out.println("Parent.set=" + other);
return other;
}
}
public class Child_1 extends Parent<Child_1>
{
}
public class Child_2 extends Parent<Child_2>
{
}
public class TestPeerage
{
public static void main(String[] args)
{
Child_1 c1 = new Child_1();
c1.set(new Child_2());
c1.set(new Child_1());
Parent<Child_1> pc1 = new Child_1();
pc1.set(new Child_2());
pc1.set(new Child_1());
}
}