Why does the following code produce the output "in super", when the object's type is the sub class (OtherClass2) and the argument to the test function is of type Person2? Shouldn't the method call test(new Person2()); call the sub class's test function?
public class HelloWorld
{
public static void main(String[] args)
{
OtherClass2 s = new OtherClass2();
s.goToThing();
}
}
public class Person
{
}
public class Person2 extends Person
{
}
public class OtherClass
{
public void hello()
{
test(new Person2());
}
public void test(Person p)
{
System.out.println("in super");
}
}
public class OtherClass2 extends OtherClass
{
public void test(Person2 g)
{
System.out.println("In sub");
}
public void goToThing()
{
hello();
}
}
public void test(Person2 g)
of OtherClass2 does not override
public void test(Person p)
of OtherClass. It overloads it. However, it only overloads it for variables whose compile time type is OtherClass2 (since overloading is determined at compile time).
Therefore
test(new Person2());
invokes the method public void test(Person p) of the super class, since OtherClass has no method with the signature public void test(Person2 g) (which could have been overridden by the test method of OtherClass2).
Had you added an #Override annotation above public void test(Person2 g), the compiler would have told you that this method is not overriding any method of the super class.
Because your test method in OtherClass2 does not override test in OtherClass (it overloads).
Would you have
public class OtherClass2 extends OtherClass
{
public void test(Person g)
{
System.out.println("In sub");
}
public void goToThing()
{
hello();
}
}
it would work as expected.
See some further details and differences between overriding and overloading.
Because hello(); method is in OtherClass. You calls goToThing() which is in OtherClass2, after that OtherClass2 calls hello() method which in OtherClass, hello() method calls test() method from OtherClass. Try this:
public class OtherClass2 extends OtherClass
{
public void hello()
{
test(new Person2());
}
public void test(Person2 g)
{
System.out.println("In sub");
}
public void goToThing()
{
hello();
}
}
Related
interface I {
public void m1();
public void m3();
}
class A implements I {
public void m1() {
System.out.println("A.m1");
this.m2(this);
}
public void m2(I obj) {
System.out.println("A.m2");
obj.m3();
}
public void m3() {
System.out.println("A.m3");
}
}
public class B extends A {
public void m2(I obj) {
System.out.println("B.m2");
super.m2(obj);
}
public void m3() {
System.out.println("B.m3");
}
public static void main(String[] args){
I obj = new B();
obj.m1();
}
}
When calling a method, the java compiler firstly checks if the apparent type of the obj has such method(in this case, it checks if the Interface I has the method m1() ) and then checks the actual type for the actual method call(and thus it calls the A's m1() method since the class B doesnt have it ).
However, why doesnt java compiler, when calling this.m2() inside A's m1() method, also checks if the Interface I has m2() method?
The output of this program is the following:
A.m1
B.m2
A.m2
B.m3
I have a class called TestingClass and I have a one more class called TestCase .
In TestingClass I have 4 methods which are dependent on each other, Can i call the this class file from my TestCase file and invoke all the methods at once?
Yes you can if they have visibility.
In your TestCase you have to declarate a variable of TestingClass and instantiate it. Then, if your methods are public you can use them.
Here is an example:
public class TestCase {
private TestingClass testingClass = new TestingClass();
#Test
public void test1(){
testingClass.methodFromTestCase();
}
}
You can try with extend the TestingClass and overwriting those methods as like,
public class TestCase extends TestingClass {
#Override
public void method1(){
super.method1();
}
#Override
public void method2(){
super.method2();
}
#Override
public void method3(){
super.method3();
}
#Override
public void method4(){
super.method4();
}
}
There is another way to do it, refer below example:
package overridefunction;
public class SuperClass
{
public void method1()
{
System.out.println("superclass method1");
this.method2();
this.method3();
this.method4();
this.method5();
}
public void method2()
{
System.out.println("superclass method2");
}
private void method3()
{
System.out.println("superclass method3");
}
protected void method4()
{
System.out.println("superclass method4");
}
void method5()
{
System.out.println("superclass method5");
}
}
package overridefunction1;
public class SubClass extends SuperClass
{
#Override
public void method1()
{
System.out.println("subclass method1");
super.method1();
}
}
package overridefunction1;
public class Demo
{
public static void main(String[] args)
{
SubClass mSubClass = new SubClass();
mSubClass.method1();
}
}
subclass method1
superclass method1
superclass method2
superclass method3
superclass method4
superclass method5
I'm trying to build a base class with a method that needs to call a private method before and after performing the actual logic.
public abstract class Base {
public Base() {}
private void before() {
// doSomething
}
private void after() {
// doSomething
}
public void actual(Object object) {
before();
// doSomething
after();
}
}
public class SomeClass extends Base {
public SomeClass() {}
public void actual(Object object) {
// actual code that needs to be executed between before and after methods.
}
}
How would I go about this?
Create another method that can be overridden and implemented instead of overriding actual directly.
E.g.
public void actual(Object object) {
before();
doActual(object);
after();
}
protected abstract void doActual(Object object);
You could make the actual() method final if you want to ensure that nobody overrides it by mistake.
You can make the method as abstract e.g.
protected abstract void actual(Object object);
and create another public method which is going to be called
public void init(Object object){
before();
actual(object);
after();
}
class SomeClass {
public void someMethod(){}
public void otherMethod(){
//Calling someMethod()
}
}
Whats the difference when you call an instance method as:
--> someMethod(); OR this.someMethod();
vs
--> SomeClass.this.someMethod();
There is no difference from doing:
//...
public void otherMethod(){
someMethod();
}
//...
to doing
//...
public void otherMethod(){
this.someMethod(); // `this` in this case refers to the class instance
}
//...
Now if you would have
class SomeClass {
public static void someMethod(){}
public void otherMethod(){
//Calling someMethod()
}
}
you could do:
//...
public void otherMethod(){
SomeClass.someMethod(); // as the method is static you don't need to call it from an instance using `this` or omitting the class
}
//...
And lastly this syntax SomeClass.this.someMethod(); would not be correct in all scenarios. An example of where this could be used (correct) is as follow:
class SomeClass {
public void someMethod(){}
public void otherMethod(){
//Calling someMethod()
}
class OtherClass {
public OtherClass() {
// OtherClass#someMethod hides SomeClass#someMethod so in order to call it it must be done like this
SomeClass.this.someMethod();
}
public void someMethod(){}
}
}
Is it possible to overload Enum abstract method?
I have tried this in my code with no effect.
Presented class
public class Test {
public void test(String string){
System.out.println(string);
}
public void test(Object object){
System.out.println("Test1");
}
public static void main(String[] args) {
Object object = new Object();
test.test(object);
test.test("what if?");
}
}
gives expected result of
Test1
what if?
while enum
public enum TestEnum {
TEST1{
public void test(String string){
System.out.println(string);
}
public void test(Object object){
System.out.println("Test1");
}
},
TEST2{
public void test(Object object){
System.out.println("Test2");
}
};
public abstract void test(Object object);
}
public class Test {
public static void main(String[] args) {
Object object = new Object();
TestEnum.TEST1.test("what if?");
TestEnum.TEST1.test(object);
}
}
returns
Test1
Test1
Is it even possible to overload Enum methods or am I doing something wrong? Or maybe should I check for type inside of overriden method and then act accordingly? But then I remove switch statement only to introduce another switch statement.
The thing about enums is that values with bodies are implemented as anonymous subclasses of TestEnum; so they look like this:
final TestEnum TEST1 = new TestEnum() { /* body */ };
Whilst the concrete class of TEST1 is, say TestEnum$1 (or whatever name the compiler decides to give it), the reference is of type TestEnum, so any code outside the body of TEST1 can only access methods defined on TestEnum.
Yes is possible, you are somehow not implementing that in a particular way....
you should
define an interface with the methods you want to override
interface Ifoo {
public void test(Object object);
public void test(String object);
}
then remove the abstract method of the enum and make the enum implement that interface, but override those methods in every constant of the enumerator...
enum TestEnum implements Ifoo {
TEST1 {
#Override
public void test(String string) {
System.out.println(string);
}
#Override
public void test(Object object) {
System.out.println("Test1");
}
},
TEST2 {
#Override
public void test(Object object) {
System.out.println("Test2");
}
#Override
public void test(String string) {
System.out.println(string);
}
};
}
finally implement it like>
Object object = new Object();
TestEnum.TEST1.test("what if?");
TestEnum.TEST1.test(object);
TestEnum.TEST2.test("why not?");
TestEnum.TEST2.test(object);
your result should looks like:
what if?
Test1
why not?
Test2
You are showing an example with a class and then you are showing an example with an enum. I believe you think these examples are equivalent, however, they are completely different each other.
For the example of your class to be equivalent to the example of your enum, you should modify your Test class so that it extends an abstract AbstractTest class:
public abstract class AbstractTest {
public abstract void test(Object object);
}
public class Test extends AbstractTest {
public void test(String string) {
System.out.println(string);
}
#Override
public void test(Object object) {
System.out.println("Test1");
}
}
Now, if you try the same lines you've tried in your first main:
AbstractTest test = new Test();
Object object = new Object();
test.test(object);
test.test("what if?");
You'll notice that the output has now become:
Test1
Test1
Which is something to be expected, because Java doesn't provide a feature called dynamic dispatch. Informally, dynamic dispatch means that the overloaded method to be executed is decided at runtime, based on the polymorphic types of the parameters. Instead, Java decides the method to be executed at compilation time, based on the declared type of the object whose method is to be invoked (in this case AbstractTest).
With enums, this is exactly what happens. All the elements of the enum (TEST1 and TEST2 in your example) belong to the type of the enum (TestEnum in your case), so the compiler always goes for the method that is declared as abstract.
The reason why you get twice "Test1" is because you have declared only this method
public abstract void test(Object object);
Precisely, this method will "catch" all calls whit any type of parameter. String extends Object (indirectly), so String is Object and this method we be called.
In other words, method wich receives parameter String will be hidden by the method which receives parameter Object.
The solution is to add next method declaration in enum
public abstract void test(String string);
You will have to add the implementation of this method to TEST2 constant.
Code
public enum TestEnum {
TEST1 {
public void test(String string) {
System.out.println(string);
}
public void test(Object object) {
System.out.println("Test1");
}
},
TEST2 {
public void test(Object object) {
System.out.println("Test2");
}
#Override
public void test(String string) {
// TODO Auto-generated method stub
}
};
public abstract void test(Object object);
public abstract void test(String string);
}
This code gives output
what if?
Test1