Java, in theory, doesn't support member overriding so I was thinking whether this code snippet can be used for overriding members of the class. However, I am not quite sure in what situations this code might fail. I mean, if this works perfectly then it wouldn't go unnoticed right?
It might be a stupid question, but I really want to know what this code might do in different situations which my mind can't think of.
So it will be really great if someone can explain it to me.
Thanks!
class ClassA{
int i = 10;
void eat() {
System.out.println("In Class A: Eating");
}
void bark() {
System.out.println("In Class A: Barking");
}
}
class ClassB extends ClassA{
//int i = 20;
ClassB(){
super.i = 20; //Changing the value of i in class A.
}
void eat() {
System.out.println("In Class B: Eating");
}
}
public class Main{
public static void main(String[] args) {
ClassB b = new ClassB();
System.out.println(b.i);
b.eat();
b.bark();
ClassA ua = new ClassB();
System.out.println(ua.i);
ua.eat();
ua.bark();
ClassA a = new ClassA();
System.out.println(a.i);
}
}
I am not quite sure in what situations this code might fail.
It (sort of) fails on the human reader/conceptual level.
The java language is what it is. This means that java programmers know what to expect, what to do, and what not to do.
And one of the basic rules for inheritance (in java, but also in general): you are extremely cautious regarding fields of your super class(es). Member fields should be considered an internal implementation detail of a class. You don't expose it to the outer world. You don't expose it to your child classes, unless there is a really good reason to do so. And if you really want to do that in java, then the correct way is: using the protected keyword for that field.
Your idea is basically that the child class "knows" about super class fields, and worse: changes that "internal state" at creation time.
Thus, in the real world, such code might quickly lead to all sorts of nasty surprises. Because people in the real world wouldn't expect that a subclass is doing something like, thus they might be really surprised to find "i should be 10, why is it 20" when debugging a problem in a large application.
Long story short: the fact that you can do something doesn't mean that you should do it. To the contrary: good programming is about doing things in "standard" ways that do not surprise your readers.
If you override a method then try to call it from the parent, the parent calls the derived method, even though it wasn't aware of it at definition time.
class A {
public void foo() {
System.out.println("A.foo");
}
public void callFoo() {
this.foo();
}
}
class B {
public void foo() {
System.out.println("B.foo");
}
}
B instance = new B();
instance.callFoo(); // Prints "B.foo"
Now if we try to do the same thing with instance fields, we get the original one.
class A {
public String foo = "A.foo";
public void printFoo() {
System.out.println(this.foo);
}
}
class B {
public String foo = "B.foo";
}
B instance = new B();
instance.printFoo(); // Prints "A.foo"
So we haven't actually overridden anything; we've simply made a new variable that happens to confusingly share the name of an existing one. If it was true overriding, then we would be able to augment the behavior of A methods which use that variable but aren't aware of the subclass.
Simple answer for your question is 'Yes', your eat method of class ClassA is overriding in class ClassB. The easy option to verify, is using #Override annotation.
In a subclass, you can override and overload an instance method. Override means, you are subclass replacing the inherited behavior. Overloading means, you are extending the inherited method.
If you modify your ClassB as follows , it will compile successfully.
class ClassB extends ClassA{
//int i = 20;
ClassB(){
super.i = 20; //Changing the value of i in class A.
}
#Override // **Added line is here**
void eat() {
System.out.println("In Class B: Eating");
}
Related
(With static and dynamic I mean the distinction whether code is susceptible to change)
I have a bit of a weird problem I'm currently stuck on. I'm writing an application which involves some complex interactions between components in which it becomes hard to keep track of the code flow. To simplify this, I'm trying to structure the code by creating 'layers', where each layer has increased functionality compared to the layer above it. Each layer is contained in a package. I'm having the following problem:
Consider the following 2 classes and their subclasses with increased functionality:
Class A:
package layer;
class A {
B b;
A() {
b = new B();
}
void foo() {
b.foo();
}
/* More A-class methods here */
}
Class B:
package layer;
class B {
void foo() {
// Do something
}
/* More B-class methods here */
}
Subclass A:
package sublayer;
class ASub extends A {
ASub() {
super.b = new BSub(); // This needs a cast to compile
}
}
Subclass B:
package sublayer;
class BSub extends B {
#Override
void foo() {
// Do something with more functionality
}
}
In the end I just want to instantiate and modify classes ASub and BSub, being able to use all methods of superclasses A and B without actually needing to modify code in classes A and B itself.
If I call new ASub().foo(), I want the overridden foo() of BSub to execute instead of that of B. Ofcourse I can add a variable BSub bsub in ASub and override A's foo() method to call bsub.foo(), but this doesnt avoid the creation of the object b in the constructor of A, which seems sloppy coding. Any thoughts on this? Any comments are welcome.
Your question is a bit controversial. Object creation and dependency injection is the subject of a lot of discussion and a core focus of various frameworks and design patterns.
But here is, I hope, one simple answer to your question, which isn't a general "what's the best way to create objects in Java?"
In the code below, I move the responsibility of instantiating B to a method (instantiateB()) which is called from the A (superclass) constructor. So, when you want to subclass A, you override that method instead of overriding the constructor.
package com.matt.tester;
public class SE {
static class A {
B b;
A() {
instantiateB();
}
void instantiateB () {
this.b = new B();
}
void foo() {
b.foo();
}
/* More A-class methods here */
}
static class B {
void foo() {
System.out.println("Hellow from B.foo()!");
}
/* More B-class methods here */
}
static class ASub extends A {
#Override
void instantiateB() {
this.b = new BSub();
}
}
static class BSub extends B {
#Override
void foo() {
System.out.println("Hellow from BSub.foo()!");
}
}
public static void main(String[] args) {
A a = new ASub();
a.foo();
}
}
Using inheritance to promote reusability is a really really bad idea. The inheritance should be always driven by the nature of the objects that you are trying to describe. You need to learn yourself to work with terms and abstractions to ask yourself "What is the nature of what I am trying to describe". My suggestion is to learn a book on Domain Driven Design for example or Code Complete. Also think about polymorphism and design patterns.
Which access modifier, in an abstract class, do I have to use for a method,
so the subclasses can decide whether it should be public or not? Is it possible to "override" a modifier in Java or not?
public abstract class A {
??? void method();
}
public class B extends A {
#Override
public void method(){
// TODO
}
}
public class C extends B {
#Override
private void method(){
// TODO
}
}
I know that there will be a problem with static binding, if
someone calls:
// Will work
A foo = new B()
foo.method();
// Compiler ?
A foo = new C();
foo.method();
But maybe there is another way. How I can achieve that?
It is possible to relax the restriction, but not to make it more restrictive:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
public void method(){ // OK
}
}
public class C extends A {
#Override
private void method(){ // not allowed
}
}
Making the original method private won't work either, since such method isn't visible in subclasses and therefore cannot be overriden.
I would recommend using interfaces to selectively expose or hide the method:
public interface WithMethod {
// other methods
void method();
}
public interface WithoutMethod {
// other methods
// no 'method()'
}
public abstract class A {
protected void method();
}
public class B extends A implements WithMethod {
#Override
public void method(){
//TODO
}
}
public class C extends B implements WithoutMethod {
// no 'method()'
}
... then only work with the instances through the interfaces.
When overriding methods, you can only change the modifier to a wider one, not vice versa. For example this code would be valid:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
public void method() { }
}
However, if you try to narrow down the visibility, you'd get a compile-time error:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
private void method() {}
}
For your case, I'd suggest to make C not implementing A, as A's abstraction implies that there's a non-private method():
public class C {
private void method(){
//TODO
}
}
Another option is to make the method() implementation in C throwing a RuntimeException:
public class C extends A {
#Override
public void method(){
throw new UnsupportedOperationException("C doesn't support callbacks to method()");
}
}
What you are asking for is not possible for very good reasons.
The Liskov substitution principle basically says: a class S is a subclass of another class T only then, when you can replace any occurrence of some "T object" with some "S object" - without noticing.
If you would allow that S is reducing a public method to private, then you can't do that any more. Because all of a sudden, that method that could be called while using some T ... isn't available any more to be called on S.
Long story short: inheritance is not something that simply falls out of the sky. It is a property of classes that you as the programmer are responsible for. In other words: inheritance means more than just writing down "class S extends T" in your source code!
This is impossible because of the polymorphism. Consider the following. You have the method in class A with some access modifier which is not private. Why not private? Because if it was private, then no other class could even know of its existence. So it has to be something else, and that something else must be accessible from somewhere.
Now let's suppose that you pass an instance of class C to somewhere. But you upcast it to A beforehand, and so you end up having this code somewhere:
void somewhereMethod(A instance) {
instance.method(); // Ouch! Calling a private method on class C.
}
One nice example how this got broken is QSaveFile in Qt. Unlike Java, C++ actually allows to lower access privileges. So they did just that, forbidding the close() method. What they ended up with is a QIODevice subclass that is not really a QIODevice any more. If you pass a pointer to QSaveFile to some method accepting QIODevice*, they can still call close() because it's public in QIODevice. They “fixed” this by making QSaveFile::close() (which is private) call abort(), so if you do something like that, your program immediately crashes. Not a very nice “solution”, but there is no better one. And it's just an example of bad OO design. That's why Java doesn't allow it.
Edit
Not that I missed that your class is abstract, but I also missed the fact that B extends C, not A. This way what you want to do is completely impossible. If the method is public in B, it will be public in all subclasses too. The only thing you can do is document that it shouldn't be called and maybe override it to throw UnsupportedOperationException. But that would lead to the same problems as with QSaveFile. Remember that users of your class may not even know that it's an instance of C so they won't even have a chance to read its documentation.
Overall it's just a very bad idea OO-wise. Perhaps you should ask another question about the exact problem you're trying to solve with this hierarchy, and maybe you'll get some decent advises on how to do it properly.
Here is a part of the #Override contract.
The answer is : there isn't any possibility to achieve what you have.
The access level cannot be more restrictive than the overridden
method's access level. For example: if the superclass method is
declared public then the overridding method in the sub class cannot be
either private or protected.
This is not a problem concerning abstract classes only but all classes and methods.
THEORY:
You have the determined modifiers order:
public <- protected <- default-access X<- private
When you override the method, you can increase, but not decrease the modifier level. For example,
public -> []
protected -> [public]
default-access -> [public, default-access]
private -> []
PRACTICE:
In your case, you cannot turn ??? into some modifier, because private is the lowest modifier and private class members are not inherited.
This problem just bit me, its pretty easy to forget to call super() when overriding a method.
In my case I was refactoring some existing stuff where there were already about ten classes overriding a method. Until yesterday the method had an empty default implementation, so it didn't matter if subclasses called super or not.
You can find the overriders just fine with any IDE worth its salt, but you know how it is, phone rings, colleagues have a smalltalk behind you back... its easy to forget to check a place or otherwise overlook it.
Ideally there would be a counterpart for the #Override annotation and the compiler would generate a warning for those places if the base class method is annotated but the override doesnt call super.
Whats the next best thing I can do?
Not quite elegant, but possible solution is to break that method into two:
public abstract class Foo {
public void doBar() {
// do your super logic
doBarInternal();
}
public abstract void doBarInternal();
}
If the superclass implementation MUST ALWAYS be called you could use the 'template method' pattern.
So what you have now is something like:
public static class Parent {
public void doSomething() {
System.out.println("Parent doing something");
}
}
public static class Child extends Parent {
public void doSomething() {
// MUST NOT FORGET SUPER CALL
super.doSomething();
System.out.println("Child doing something");
}
}
public static void main(String[] args) {
Child child = new Child();
child.doSomething();
}
And this would become:
public abstract static class Parent {
public final void doSomething() {
System.out.println("Parent doing something");
childDoSomething();
}
public abstract void childDoSomething();
}
public static class Child extends Parent {
public void childDoSomething() {
System.out.println("Child doing something");
}
}
public static void main(String[] args) {
Child child = new Child();
child.doSomething();
}
(classes are made static for easy testing within one class)
I made doSomething final to avoid it being overridden since in this solution childDoSomething should be implemented instead.
Of course this solution means Parent can no longer be used as a concrete class.
EDIT: after reading comments about Child implementing a third party interface; this does not need to be a problem:
public interface ThirdPartyInterface {
public void doSomething();
}
public abstract static class Parent {
public final void doSomething() {
System.out.println("Parent doing something");
childDoSomething();
}
public abstract void childDoSomething();
}
public static class Child extends Parent implements ThirdPartyInterface{
public void childDoSomething() {
System.out.println("Child doing something");
}
// public final void doSomething() {
// // cannot do this because Parent makes it final
// }
}
public static void main(String[] args) {
Child child = new Child();
child.doSomething();
}
Loooking for something else I found interesting OverrideMustInvoke annotation in FindBugs:
http://findbugs.sourceforge.net/api/edu/umd/cs/findbugs/annotations/OverrideMustInvoke.html
If you do not insist on compile time safety you could use a mechanism that throws an exception whenever a subclass does not behave as logically required: How do I force a polymorphic call to the super method?
I have 2 different suggestions:
1) Build a junit test that discovers all subclasses of your base class, and then selects all the methods decorated with the #Override annotations. I have some unit tests that do something similar (i.e. find all subclasses, check that they truly are Serializable for example).
Unfortunately, the verification of whether they call "super" is a little less straightforward. You would either need to have the test look up the source file, and search it, or better (but I don't know how to do this), read the byte code and see if you can detect the call to super.
2) Needing to guarantee a call to super is probably an indicator of a design/interface issue, rather than a coding/implementation issue. If you really want to guarantee that users call super, it would be better to make the super class abstract, clearly designate an abstract implementation method for them to override, and have the super control the flow of execution.
If you want to define a default implementation, so that not all users need to subclass provide implement that method, you could define a default implementation class for people to use. (And if you really want to control it, define that default class implementation method as final to force them to go back to subclassing the abstract parent.)
Code reuse inheritance is always harder to manage, and so it needs to be done carefully. Anyone doing code reuse inheritance has to have a good idea of the internals of the super class to do it right (which is a bit yucky). For example, do you have to call super.method() at the beginning of your overriding code, or at the end? (or could you do it in the middle...)
So in summary, the best solution is to try avoid a design where you have to enforce that.
What could work - creating some marker annotation (i.e. #MustCallParent) and then create some annotation processor to check that methods marked with it comply to the constraint.
This isn't exactly the definition of implicit type conversion, but I'm curious how many standards I'm breaking with this one...
I'm creating an abstract class in Java that basically casts its variables depending on a string passed into the constructor.
For example:
public abstract class MyClass {
Object that;
public MyClass(String input){
if("test1".equals(input){
that = new Test1();
}
else{
that = new Test();
}
}
public void doSomething(){
if(that instanceof Test1){
//specific test1 method or variable
} else if(that instanceof Test2)}
//specific test2 method or variable
} else {
//something horrible happened
}
}
}
You see what I'm getting at? Now the problem I run into is that my compiler wants me to explicitly cast that into Test1 or Test2 in the doSomething method - which I understand, as the compiler won't assume that it's a certain object type even though the if statements pretty much guarantee the type.
I guess what I'm getting at is, is this a valid solution?
I have other classes that all basically do the same thing but use two different libraries depending on a simple difference and figure this class can help me easily track and make changes to all of those other objects.
You are right. This is a horrible way to achieve polymorphism in design. Have you considered using a factory? A strategy object? It sounds like what you are trying to achieve can be implemented in a more loosely-coupled way using a combination of these patterns (and perhaps others).
For the polymorphism of doSomething, for example:
interface Thing {
public void doThing();
}
class Test1 implements Thing {
public void doThing() {
// specific Test1 behavior
}
}
class Test2 implements Thing {
public void doThing() {
// specific Test2 behavior
}
}
class MyClass {
Thing _thing;
public void doSomething() {
_thing.doThing(); // a proper polymorphism will take care of the dispatch,
// effectively eliminating usage of `instanceof`
}
}
Of course, you need to unify the behaviors of Test1 and Test2 (and other concrete Thing classes, present and planned) under a set of common interface(s).
PS: This design is commonly known as Strategy Pattern.
I would create a separate class file. So you would have something like this:
1. You abstract "MyClass"
->within "MyClass" define an abstract method call doSomething...this will force the specific implementation of the method to it's subclasses.
2. Test1 would be the implementation of MyClass which would contain the implementation of the doSomething method
3. Create a utility class that does the check "instanceOf" that check should not be in the constructor it belongs in another class.
So in the end you would have 3 class files an Abstract Class, Implementation of the Abstract and a Class that does the "instanceOf" check. I know this sounds like a lot but it's the proper way to design, for what I think you are attempting to do. You should pick up a design patterns book, I think it would help you a lot with questions like these.
The Open-Closed principle would be better satisfied by moving the object creation outside of this class.
Consider changing the constructor to accept an object that implements an interface.
public MyClass {
public MyClass( ITest tester ) { m_tester = tester; }
public void doSomething(){ m_tester.doTest(); }
}
This makes it possible to change the behavior of the class (open to extension) without modifying its code (closed to modification).
The better way to do this is to create an interface which will specify a set of methods that can be guaranteed to be called on the object.
Here's an example:
public interface TestInterface
{
void doTest();
}
Now you can write your classes to implement this interface. This means that you need to provide a full definition for all methods in the interface, in this case doTest().
public class Test implements TestInterface
{
public void doTest()
{
// do Test-specific stuff
}
}
public class Test1 implements TestInterface
{
public void doTest()
{
// do Test1-specific stuff
}
}
Looks really boring and pointless, right? Lots of extra work, I hear you say.
The true value comes in the calling code...
public abstract class MyObject
{
Test that;
// [...]
public void doSomething()
{
that.doTest();
}
}
No if statements, no instanceof, no ugly blocks, nothing. That's all moved to the class definitions, in the common interface method(s) (again, here that is doTest()).
I Have something similar to this setup:
public class Base {
public String getApple() {return "base apple"};
}
public class Extended extends Base{
public String getApple() {return "extended apple"};
}
Somewhere else in the code I have this:
{
Base b = info.getForm();
if (b instanceof Extended){
b = (Extended) b;
}
System.out.println(b.getApple()); // returns "base apple" even when if clause is true why??
}
How do I accomplish that?
First:
if (b instanceof Extended){
b = (Extended) b;
}
does absolutely nothing. You are basically saying b = b, which says nothing. You are not even changing the reference.
Second, getApple() will always be dynamically bound, and the "extended apple" should always be called - given that the subclass is truly extending the base class, and the method is truly overridden.
Basically what you need to do, in order to accomplish correct getApple() behavior:
remove the if clause. it does nothing.
make sure your class is indeed extending the base class
make sure the getApple() method is overriding the base class method. (use the #override annotation if you are not sure)
As written, your code will not compile, which makes me think that your problem is elsewhere. Your return statements don't have semicolons at the end of them. Rather, they appear after the }. It's possible you had some other problem (maybe your subclass misspelled getApple()), but you're still using your old class files because your new stuff isn't compiling.
This code works:
class Base {
public String getApple() { return "base apple"; }
}
class Extended extends Base {
public String getApple() { return "extended apple"; }
}
public class Test {
public static void main(String[] args) {
Base b = new Extended();
System.out.println(b.getApple());
}
}
Console:
#javac Test.java
#java Test
extended apple
First of all, that if block should never be necessary. It's basically a no-op.
Second, this isn't your real code, because it doesn't even compile. You're missing semicolons after the return statements.
I suspect that your problem is that your real code has a typo that's making the signatures of the two getApple methods different. This means that Extended has two methods: the one inherited from Base and the one with a different signature in itself. Since you're calling with the signature of the Base.getApple method, you're always getting that behavior. This is only a guess though, as your posted code does not exhibit the problem you describe.
Yuval is right that your cast in the if block has no effect. You might try combining your last statement with the if:
if (b instanceof Extended)
{
// Prints "extended apple" if reached.
System.out.println(((Extended)b).getApple());
}
Add #Override to the method in your subclass and recompile. This will help you find out if you're not actually overriding the method you think you are.
i.e.
public class Base {
public String getApple() {return "base apple";}
}
public class Extended extends Base{
#Override
public String getApple() {return "extended apple";}
}
The only way to get that behavior is to return super.getApple() in your extended class, which is effectively the same as not overriding it in the first place. The only way this could help is if you pass in an argument to decide which to return. Not saying thats good design...
Forgot to mention that, as Yuval said, the cast does nothing to the object.
You should investigate what is constructing your instance that is returned from info.getForm(). You may want to make the Base abstract to prevent it from being instantiated and you'll quickly see where construction is happening.
Are you sure your code example provided in your question EXACTLY matches the code your are using? The reason I ask is that the behavior you are describing happens when you access a public FIELD instead of a public METHOD with an object pointer.
For example:
public class BaseClass {
public String baseField;
public BaseClass() {
baseField = "base";
}
public String getBaseField() {
return baseField;
}
}
public class SubClass extends BaseClass {
public String baseField;
public SubClass () {
baseField = "sub";
}
public String getBaseField() {
return baseField;
}
}
public class MainClass {
public static void main(String[] args) {
BaseClass baseObject = new BaseClass();
SubClass subObject = new SubClass();
System.out.println(baseObject.getBaseField());
System.out.println(subObject.getBaseField());
System.out.println(baseObject.baseField);
System.out.println(subObject.baseField);
System.out.println(((BaseClass)subObect).getBaseField());
System.out.println(((BaseClass)subObect).baseField);
}
}
Will print out:
base
sub
base
sub
sub
base
When you call a method, the JVM will start at the bottom of the inheritance hierarchy and call the appropriate method. When you reference a field instead, it uses the class of the pointer instead of walking up the class hierarchy to resolve the value. The behavior of the field reference matches what you're seeing, which is why I ask for clarification/verification.