For example, I have an interface with 4 methods.
If I implement this interface incomplete in a class, the class must be abstract. Right?
For example, I leave one method out. So now I am writing a subclass which extends this class. Now I implement the last method of the interface.
What happens, if I call this method in the abstract superclass? Nothing! It works. But why?
What will happen, if I write several classes, extending this abstract class and implement the fourth method of the interface? Which one will be called?
A interface is a contract you define the signature of your methods, only behaviour and constants, all methods are public and abstract.
In an Abstract Class you define behaviour and state, you can have some implementation and abstract methods.
For example for your question:
If I implement this interface incomplete in a class, the class must be
abstract. Right?
Right
For example, I leave one method out. So now I am writing a subclass
which extends this class. Now I implement the last method of the
interface.
What happens, if I call this method in the abstract superclass?
Nothing! It works. But why?
Will run cause in runtime execution knows what class is. this is polymorphism.
What will happen, if I write several classes, extending this abstract
class and implement the fourth method of the interface. Which one will
be called?
The one you instanciate in your client code :D
public interface Operation{
void operation1();
void operation2();
}
I don't implement operation2
public abstract class ClaseBase implements Operation{
//with final im saying childs wont override
public final void operation1{
// do something
operation2();
// do something
}
}
//have to implements operation2 cause it's a concrete class
public class Child extends ClaseBase{
void operation2(){
System.out.println("Something");
}
}
You can't instanciate an AbstractClass.
In your client code
ClaseBase base = new Child();
base.operation1(); // and it's gonna to call operation2 in childClass
Abstract class is useful with Template Method pattern.
It depends on the object that you created. Super class can refer to subclass objects. So the actual object's method would be called.
interface A{
public void test1();
public void test2();
}
public abstract class B implements A{
public void test1(){
}
public abstract public void test2();
}
public class C extends B{
public void test2(){
}
}
B b = new C();
b.test2();//This works because the object that is refered by B is actually an object of C
Infact you can also do:
A a = new C();
a.test1();
a.test2();
Again though A is an interface(super type), but it is actually referring to a concrete implementation C(subtype) object and hence this works.
So at the compile time, compiler checks if A/B has a method called test2(), if yes compile is happy and it compiles successfully. But at the runtime, you invoke test2() method on the object and object actually is of class C which has the complete implementation.
Keep in mind that when you instantiate a subclass and refer it as super/abstract class or interface, it's still the instance of the subclass. Any method called on the object bubbles up from subclass to super class if its not available in the sub class.
Thus if you have:
interface GemeInterface
getStartScreen()
getCloseScreen()
abstract class AndroidGame implement GemeInterface
getCloseScreen()
class MrNomGame extends AndroidGame
getStartScreen()
class MrPetNomGame extends AndroidGame
getStartScreen()
and using as
//You can't instantiate AndroidGame hence the it has to be instance of a subclass
AndroidGame androidGame1 = new MrNomGame ();
androidGame1.getStartScreen();
//You can't instantiate AndroidGame hence the it has to be instance of a subclass
AndroidGame androidGame2 = new MrPetNomGame ();
androidGame2.getStartScreen();
Then also it works as androidGame1.getStartScreen() --> calls the method from MrNomGame, while androidGame2.getStartScreen() --> calls the method from MrPetNomGame.
Both the calls i.e. androidGame1.getCloseScreen() and androidGame2.getCloseScreen() will end up calling the method from AndroidGame as it's not available in the sub classes.
What happens, if I call this method in the abstract superclass? Nothing! It works. But why?
You cannot invoke this method on the abstract superclass because it can't be instantiated. You would only be invoking it on a sub-class of this abstract super-class which would be forced to provide an implementation (or be declared abstract itself).
So, when you invoke this method, its the implementation provided by the non-abstract sub-class that gets executed.
The funny thing is that a method of the class 'AndroidGame' calls 'getStartScreen()'. But there could be several classes like 'MrNomGame' which extending 'AndroidGame'. Then which method would be executed?
The method code executed would depend on the runtime type of the actual object that you invoke this method on. So, you could have a code like this
AndroidGame game1 = new MrNomGame();
AndroidGame game2 = new SomeOtherGame();
game1.getStartScreen(); // invokes MrNomGame's version
game2.getStartScreen(); // invokes SomeOtherGame's version
and due to dynamic binding the JVM would invoke the getStartScreen() as implemented by the class type of the actual object that the reference points to.
Related
I'd like to know what really happens when somebody calls java super() method in the constructor of a class that inherits from an abstract class. As we know it, an abstract class cannot be instantiated but super calls the constructor of the abstract class.
Let's take an example.
public abstract class Figure { // cant be instantiated
private type firstAttribute;
private type secondAttribute;
public Figure(type firstAttribute, type secondAttribute) {
this.fisrtAttribute = fisrtAttribute;
this.fisrtAttribute = fisrtAttribute;
}
protected abstract void anyMethod();
}
class Rectangle extends Figure {
public Rectangle(type firstAttribute, type secondAttribute) {
/*
* call the abstract class constructor but we know, a
* constructor is used to
* instantiate class and we can't instantiate an abstract class
*/
super(firstAttribute, secondAttribute);
// then what really happen ?
}
#override
....
}
The confusion stems from the fact that calling the super() constructor doesn't actually instantiate the super class. It simply invokes the super() constructor. No more, no less.
This means that the code in the super constructor will be called when super() is called. You're correct that abstract classes cannot be instantiated, but invoking the super constructor from a subclass constructor doesn't count as instantiation.
The abstract base class initialised any properties you inherit in your concrete inheriting class, so you can avoid code duplication in the initialisation
I executes the code in the constructor it calls.
There is no need to create an instance of the abstract class for that; after all, during constructor invocation, the instance of the class is never created already.
I am writing a program in Java and having a problem with inheritance.The code I am running has this structure:
public class BaseClass
{
ObjectInputStream a;
ObjectOutputStream b;
public BaseClass(ObjectInputStream a, ObjectOutputStream b)
{
this.a = a;
this.b = b;
}
//Some other code....
Thread subClass = new Thread(new SubClass());
subClass.start();
}
And then here is the SubClass:
public SubClass extends BaseClass implements Runnable
{
//Code for SubClass...
}
Then, when I compile the code, the only error I receive is
./SubClass.java:6: error: constructor BaseClass in class BaseClass'
cannot be applied to given types;
public class SubClass extends BaseClass implements Runnable
^
required: ObjectInputStream,ObjectOutputStream
found: no arguments
I am assuming that the problem is coming from the fact that I am extending a BaseClass that has a constructor, so it is invoked when I inherit the class, but I am not completely sure. Is there a way for me to invoke that constructor with the correct arguments? Or, better yet, a way to not invoke the constructor at all? Any help is appreciated, and thank you for your responses.
Your subclass should have a constructor that takes in
ObjectInputStream a, ObjectOutputStream b
and than pass it to the base class using
super(a, b):
I believe it would look like this:
class Subclass extends BaseClass {
SubClass(ObjectInputStream a, ObjectOutputStream b) {
super(a, b);
}
}
EDIT---
You can't 'not call' constructor. Even if base class has default constructor (no arguments), it will be implicitly called from your sub class.
You don't have a call for super - the parent cunstractor:
public SubClass extends BaseClass implements Runnable
{
//must implement the following contractor:
public SubClass(ObjectInputStream a, ObjectOutputStream b /*some other parameters*/){
super(a,b);
}
// the rest of the code.....
}
The base class has no default constructor, witch implies that it must receive one ObjectInputStream and one ObjectOutputStream. So, SubClass must have a constructor like this, or one that call super, passing the arguments. I would like you to:
Review your inheritance
See if Base Class could have a default constructor
Create a default constructor in SubClass passing null to super -> super(null,null)
Create a default constructor in SubClass passing the two objects required
There's is no way to not call the parent constructor. The compiler automagically adds the call super to you.
The basic idea behind inheritance is that the public methods and variables of the Superclass will be available in the Subclass. (There is more to it than just this statement, but this should suffice for now). So in your case, when you extend the BaseClass to the SubClass, you have the two variables ( ObjectInputStream and ObjectOutputStream) available to you in the SubClass.
Thus you HAVE to provide them with some initial values when you create an Object of the SubClass. Hence you should add the following constructor to your SubClass.
public SubClass(ObjectInputStream a,ObjectOutputStream b){
super(a,b); // The order in super should be same as the order of arguments in your BaseClass constructor! Make a not of this.
}
Note: The order of arguments in the super() method is important!
When you create a class that inherits from another class, one of the implications is that you are going to depend on some code in the base class. That means you need to setup the base class properly. Since your base class has only that one constructor that takes parameters, your class needs to provide a constructor that takes the same parameters so it can initialize its base class. So you need to add an additional constructor that takes the same parameters as the base class.
I am just confused about abstract class concept. Please clear my doubt. Definition of Abstract class says we can not create object of such class, then what we called like A a = new A() { }. Example is below:
public abstract class AbstractTest {
public abstract void onClick();
public void testClick() {
}
}
public class A {
AbstractTest test = new AbstractTest() {
#Override
public void onClick() {
}
};
}
Then test is a object or what?
test is an object of an anonymous concrete sub-class of AbstractTest (note that it implements all the abstract methods of AbstractTest), which is why this sub-class can be instantiated.
On the other hand,
AbstractTest test = new AbstractTest();
wouldn't pass compilation, since that would be an attempt to instantiate an abstract class.
You are mixing up object and reference.
AbstractTest test = new AbstractTest() {
#Override
public void onClick() {
}
};
test here is a reference to a anonymous class that extends AbstractTest, the above code is like saying:
class MyClass extends AbstractTest {
#Override
public void onClick() {
}
}
AbstractTest test = new MyClass(); // test is a reference to a MyClass object
Abstract Class in my opinion needs to be explained together with Interface.
Interface allows you to specify operations that are supported/allowed on objects with that interface. More specifically Objects are instances of a Class which implements that Interface. Defining an interface allows you to describe a group of different classes of objects so that other objects can interact with them in the same manner.
Abstract Class is one step between interface and a Class (loosely speaking). Abstract Class allows you to specify operations that are supported by classes that extend it, but it also allows you to implement (some of) those operations. This way you can implement common methods for a group of classes in that abstract class. Other methods in the abstract class that are not implemented (aka abstract methods) need to be implemented by the class that extends it. The fact that you didn't implement all methods on an Abstract class naturally means you can't instantiate it (create an object of such class). There are other useful implementations for Abstract classes (i.e. callbacks).
In your example what you see there is that you are not really trying to just create an object that Abstract class you are also providing implementation of abstract method onClick();
That is the only way you can "create an instance of the abstract class" - technically speaking you are creating an instance of an Anonymous class (that is extending your abstract class) for which you provide implementation of inherited abstract methods.
I have a class java ProductManager which extends another class with the same name,
located in another project with another package("com.services") .
I have to invoke a method deleteProduct(Long productId) located in the super-class.
try{
Object service = CONTEXT.getBean("ProductManager");
Method method = service.getClass().getDeclaredMethod("deleteProduct", Long.class);
method.invoke(service, productId);
} catch(Exception e){
log.info(e.getMessage());
}
I couldn't delete the product:
I get this info:
com.franceFactory.services.ProductManager.deleteProduct(java.lang.Long)
the product isn't deleted :(
The various getDeclaredMethod() and getDeclaredMethods() only return methods declared on the current class instance. From the javadoc:
This includes public, protected, default (package) access, and private methods, but excludes inherited methods.
The important part here is "but excludes inherited methods". This is why you are getting an exception with your code as it currently stands, it is not returning the deleteProduct() method from the parent class.
Instead if you wanted to continue using reflection you would need to use the getMethod method as this returns all public methods, "including those declared by the class or interface and those inherited from superclasses and superinterfaces."
If you have to use reflection then don't use getDeclaredMethod() because (as its name suggest) it can return only methods declared in current class, while you claim you want to invoke method declared in other class (to be precise declared in super class).
To get public method (including also inherited ones) use getMethod().
If your are overriding that method, just use the reserved word super (from the Oracle documents):
public class Superclass {
public void printMethod() {
System.out.println("Printed in Superclass.");
}
}
public class Subclass extends Superclass {
// overrides printMethod in Superclass
public void printMethod() {
super.printMethod(); // This calls to the method defined in the superclass
System.out.println("Printed in Subclass");
}
public static void main(String[] args) {
Subclass s = new Subclass();
s.printMethod();
}
}
This code will write:
Printed in Superclass.
Printed in Subclass
In other case (you are not overriding it, just using it), just write this.methodName(...). All methods inherited are directly available.
Disclaimer: I am not sure I totally understand your question. I will still try to answer what I think I understand.
The Product in package com.franceFactory.services (Lets call it A)
extends The Product class in package com.services (Lets call it B)
So A extends B.
B has method deleteProduct(java.lang.Long)
A overrides the method deleteProduct(java.lang.Long)
You have instance of Class A. So by OOPS concept method deleteProduct of object A is going to get called.
There is no way you can call the super method from outside unless you have the instance of class B.
EDIT
OPs Clarification yes, it's public, but it isn't overridden in my class
The method in super is getting called here. The product is not getting deleted for reason on what is written on the method.
I have a class (called SubClass for simplicity) that extends SuperClass and implements IClass.
I know that you can call SuperClass' methods by using super.method(), but is it possible to call a method from SubClass which it implements from IClass?
Example:
public class SuperClass {
public void method(){
implementedMethod();
}
}
Subclass:
public class SubClass extends SuperClass implements IClass{
public void implementedMethod() {
System.out.println("Hello World");
}
}
IClass:
public interface IClass {
public void implementedMethod();
}
I would like to call SubClass' implementedMethod() (Which it gets from IClass) from SuperClass
How would I go about doing that?
You can make the super class abstract:
public abstract class SuperClass implements IClass {
public void method(){
implementedMethod();
}
}
Given the types above, anExpressionOfTypeSubClassOrIClass.implementedMethod() must be used. Note that the Type of an expression - the view it provides - must have the method intended to be used. In this case, an expression of type SuperClass cannot be used here because it has no declared implementedMethod member.
One approach - and arguably the preferred approach - is to use abstract methods. Even though abstract methods are not strictly required for Polymorphism they describe scenarios such as this where a subclass should provide the implementation. (The abstract methods could be replaced with empty method expecting - but not requiring - to be overridden in sublcasses, but why not use abstract for its designed purpose?)
abstract class SuperClass implements IClass {
// Don't implement this, but declare it abstract
// so that we can conform to IClass as well
public abstract void implementedMethod();
public void method () {
// Now this object (which conforms to IClass) has implementedMethod
// which will be implemented by a concrete subclass.
implementedMethod();
}
}
This has the "negative" aspects that SuperClass cannot be directly instantiated (it is abstract, after all) and that SuperClass must implement (or, as shown, delegate out via abstract) the expected signature. In this case I also chose to make SuperClass implement IClass even though it's not strictly required because it guarantees that the SuperClass and all subclasses can be viewed as an IClass.
Alternatively, remember that Types of Expressions are just views of objects and are not necessarily the same as the actual Concrete Type of object. While I would advise against using the following code because it loses some type-safety, I think it shows the important point.
class SuperClass {
public void method () {
// We try to cast and NARROW the type to a
// specific "view". This can fail which is one
// reason why it's not usually appropriate.
((IClass)this).implementedMethod();
}
}
class SubClass extends SuperClass implements IClass {
// ..
}
class BrokenSubClass extends SuperClass () {
}
// OK! Although it is the SAME OBJECT, the SuperClass
// method can "view" the current instance (this) as an IClass
// because SubClass implements IClass. This view must be
// explicitly request through a cast because SuperClass itself
// does not implement IClass or have a suitable method to override.
(new SubClass()).method();
// BAD! ClassCastException, BrokenSubClass cannot be "viewed" as IClass!
// But we didn't know until runtime due to lost type-safety.
(new BrokenSubClass()).method();
The only way to call that method would be to create an object of type SubClass (in SuperClass) and call subClassInstance.implementedMethod().
I also want to stress that this is very inelegant. As stated in a comment on your question, you should reconsider your class designs if your superclass needs to call a subclass method.