I am confused about how to create methods in a subclass. I am hitting my head against a brick wall with this and not even sure how to word the question.
import java.io.*;
public class A {
public double method1(double x, double y) { return 1.0; }
}
class B extends A {
//subclass method to be placed after this line
}
public double method1(double x, double y) { ... }
public int method1(double x, double y) { ... }
public double method1(int x, int y) { .... }
public int method1(double x, double y, double z) { ... }
Which of the following methods will be legal in the subclass and why?
Overrides method1 with new functionality.
Illegal because it has the same parameter signature but a different return type.
3,4. legal but are really separate methods.
Just consider the argument types to be part of the method name:
Only if the name plus the argument types fully match, you override the same method with new functionality. In this case, the return type must match (starting with Java 1.5, the return type may be specialized in subclasses, see https://blogs.oracle.com/sundararajan/entry/covariant_return_types_in_java)
In other cases, the added methods are just separate methods with the same name. Java statically picks the right one for each invocation at compile time based on the provided argument types. If arguments are compatible and the names are the same for multiple methods, it picks the closest match.
If you put the following methods in class, as per my understanding, this should happen:
public double method1(double x, double y) { ... }
This is overridden method, which means you overriding the behavior of method1 in your subclass, which is perfectly legal.
public int method1(double x, double y) { ... }
Compilation error: This is a try to do method overloading but not in a legal way. Method overloading allows to have same method name but different type/number of arguments. Method overloading is done with different parameter list but NOT by using a different return type.
public double method1(int x, int y) { .... }
This one is a legal overloaded method
public int method1(double x, double y, double z) { ... }
Again a legal overloaded method
Overrides the method in A and is legal
Is illegal because returntype is different and not a specialisation of the returntype of the method in A
Is an overloaded method because the argument types are different
Is an overloaded method because there are more parameters
See also http://en.wikipedia.org/wiki/Function_overloading and http://en.wikipedia.org/wiki/Method_overriding
Legal overriding
Not Legal overriding because return type should be covarient or same
legal overloading
legal overloading
overriding rules :- * parameter must same
return type must same or it should be covarient
exception if it is checked it should be sub class of that overridden method
access modifier should be same or less restricted
overloading rules :- * parameter must different
return type can be same
access modifier can be same
Read Katherine Sierra, Bert Bates (SCJP Book) for full rules or Java doc
Related
Playing around with ambiguous methods calls that have multiple parameters, I noticed that quite often it was not actually ambiguous when I expected it to be, and this led to some strange behavior that I couldn't quite understand.
For example, with the following inheritance structure:
public static class A {
}
public static class B extends A {
}
public static class C extends B {
}
And running the method test().
public static void test() {
test(new C(), new C(), new C());
}
For some reason these two methods are ambiguous
public static void test(A x, A xx, B xxx) {
System.out.println("TEST 1");
}
public static void test(A x, C xx, A xxx) {
System.out.println("TEST 2");
}
However swapping the last two arguments in the second method makes that one take priority.
public static void test(A x, A xx, B xxx) {
System.out.println("TEST 1");
}
public static void test(A x, A xx, C xxx) {
System.out.println("TEST 2"); //No longer ambiguous, this one is called
}
Can someone please explain this behavior, and also in general exactly how quasi-ambiguous method calls are determined in Java with multiple parameters?
Reading through the Java Language Specifications chapter on choosing the most specific method, the following statements are important to note:
One applicable method m1 is more specific than another applicable
method m2, for an invocation with argument expressions e1, ..., ek,
if ...
...m2 is not generic, and m1 and m2 are applicable by strict or
loose invocation, and where m1 has formal parameter types S1, ..., Sn
and m2 has formal parameter types T1, ..., Tn, the type Si is more
specific than Ti for argument ei for all i (1 ≤ i ≤ n, n = k).
What this basically means is that given two (non varargs) method signatures that can match a method call, the compiler will choose the more specific method, and the more specific method is the one where each parameter is more specific than (i.e. either the same class as or a subclass of) the corresponding parameter in the other signature (ignoring generics here for the sake of simplicity).
So, for example when you have (A,A,B) and (A,A,C), the latter is more specific because A = A and C is a subclass of B, so the choice is clear and unambiguous.
But when you have (A,A,B) and (A,C,A), the former can't be more specific because C is a subclass of A, but the latter can't be more specific either because B is a subclass of A. Hence, ambiguity.
Its because both of test methods can accept instances of C as its arguments as C can act as B and A
public static void test(A x, A xx, B xxx) {
System.out.println("TEST 1");
}
public static void test(A x, C xx, A xxx) {
System.out.println("TEST 2");
}
The problem here is that both methods apply to (A, C, B). In this specific circumstance ambiguity is present.
With the unambiguous example you provided there is no signature common to both declarations:
public static void test(A x, A xx, B xxx) {
System.out.println("TEST 1");
}
public static void test(A x, A xx, C xxx) {
System.out.println("TEST 2"); //No longer ambiguous, this one is called
}
The first applies to (A, A, B), the second applies to (A, A, C). The second is merely overriding the former in providing a more specific use case (signature). You might want to consider it as overriding the former, although that probably isn't the technical term.
By extension C is a A so given the choice of calling methods where the parameter is C or A the interpreter will call either (hence ambiguity can arise) but must call the one with the more specific parameter, if available. This can be described as polymorphism; the run time type of the instance is used to determine the class and method calls are searched from the descended class up.
As JB Nizet points out, the language specs are the authority here, but I like to experiment too.
I try to explain you what would be the problem.
For instance I have a class that contains three methods that with different parameters calculates the multiplication of two numbers.
These methods are:
long mul(int x, long y)
long mul(long x, int y)
long mul(long x, long y)
Because the overloading all these methods are valid and calculate the same thing: the result of the multiplication beetween x and y.
Suppose to have two variables which are the parameters for the method:
int x;
long y;
If I call mul(x,y) then I will get x*y as result because mul(int, long) is the most
specific method for these parameters.
If I call mul((long) x, y) then I will get again x*y because mul(long, long) is the most specific method for these parameters.
Instead if I call mul(x, x) I wont' get x*x because the language (Java) can't guess what is the best casting for the parameters.
Calling mul(x, x) leads to this dilemma: I should cast x to long, so calling mul(long ,long) or I should cast y to int, so calling mul(int, int).
This is the problem that you can find while using overloading.
I hope I help you!
Can the contains method be used on instances of classes I've written myself?
I've created a class named Ana and in another class, I've created two instance of it called cookie and maccaroni. This is one of them:
Ana cookie = new Ana(cc.c, 20, 450);
At some point I am trying to invoke
if (maccaroni.contains(cookie.image(), cookie.xi(), cookie.yi())
{
return true;
}
but Netbeans underlined it to indicate a mistake. When I hovered over it, it said:
no suitable method found for contains(Image,int,int)
method Component.contains(int,int) is not applicable
(actual and formal argument lists differ in length)
method Component.contains(Point) is not applicable
(actual and formal argument lists differ in length)
method JComponent.contains(int,int) is not applicable
(actual and formal argument lists differ in length)
Why the following code is regarded as a mistake by Netbeans?
This is the class I'm referring to.
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JComponent;
public class Ana extends JComponent
{
public static Image p;
public static int xx;
public static int yy;
public Ana(Image io, int x, int y)
{
p = io;
xx = x;
yy = y;
repaint();
}
#Override
public void paint(Graphics g)
{
g.drawImage(p, xx, yy, null);
}
public Image image()
{
return p;
}
public int xi()
{
return xx;
}
public int yi()
{
return yy;
}
}
There is no contains() method defined in Ana. There is a contains() method defined in JComponent. It takes two integers. You're trying to invoke it with an image and two integers. You can probably get what you need by writing it like this:
if (maccaroni.contains(cookie.xi(), cookie.yi())
{
return true;
}
So the kind of error in this code is: it's a compile error. NetBeans isn't just underlining it, there is a message somewhere on your screen telling you what is wrong. You may have to mouse over the underline or look in a different section of the screen--I don't use NetBeans on a regular basis so I don't recall exactly--but I assure you the message is there.
And no, you can't invoke contains() on any object, only on objects which classes define a contains() method (with proper parameters), or that inherit such a method from one of their supertypes (from an ancestor class or interface they implement).
Methods which all objects could use are those inherited from java.lang.Object class, since all classes explicitly or implicitly extend it (parent of parent of parent... finally will need to extend the Object class).
But there is no contains(Image, int, int) method defined on java.lang.Object. The only contains() method available to instances of the Ana class is the one inherited from JComponent which is contains(int, int). As you see it accepts two int arguments, which prevents you from using it with the additional Image argument.
By the way, as #PShemo has noted, your fields p, xx and yy should likely be private and most definitely not static.
I know that a method can be overriden with one that returns a subclass.
Can it also be overloaded by a method which returns a subclass?
public Object foo() {...}
public String foo(int a) {...}
Is the above code valid?(if placed within a Class)
What about?
public Object foo() {...}
public String foo() {...}
Beginning with Java 5, covariant return types are allowed for overridden methods. This means that an overridden method in a subclass is allowed to use a signature which returns a type that may be a subclass of the parent signature's return type.
To make this concrete, say you have this interface:
public interface MyInterface {
Number apply(double op1, double op2);
:
:
}
The following is legal because the return type is a subclass of Number:
public class MyClass implements MyInterface {
:
:
#Override
public Integer apply(double op1, double op2) {
:
:
return Integer.valueOf(result);
}
}
Because overloaded methods (which have the same name but different signatures) are effectively different methods, you are free to use different return types if you like ... however ... this is discouraged because methods that have the same name but different return types can be confusing to programmers and can complicate the use of your API. It's best not to overload mrthods when you can reasonably avoid it.
This example:
public Object foo() {...}
public String foo(int a) {...}
as long as the two methods get different set of variables, there's no problem with returning different types (even if they are not subclass).
The logic is very simple - if the compiler can choose without doubt which one to use - there's no issue. In this case- if you give the method int it's one method, and without parameters it's the other, no dilema (and the same name does not matter here)
as for:
public Object foo() {...}
public String foo() {...}
This one is not valid, since here the compiler can't 'choose' which one to use.
Yes, and it does not even need to be a subclass foo(), and foo(int) are two completely different and unrelated functions as far as the compiler is concerned, each can have any return type you want.
yeah, you overroad foo with foo(int a) , and gave it a new data type String , the compiler see this as a valid code but the other one Object foo() and String foo() is totally invalid in java
Question:
I have the following:
interface A
{
int MethodA(int x, int y);
}
and
interface B extends A
{
//This is meant to overload MethodA
int MethodA(int x, int y, int z);
}
The problem comes when I try to implement interface B, and run the method in main.
class Foo implements B
{
//For interface B
public int MethodA(int x, int y, int z)
{
//Actual implementation
}
//For interface A
public int MethodA(int x, int y)
{
//Actual implementation
}
}
public static void main(String[] s)
{
Foo foo = new Foo();
//Problem occurs here
foo.MethodA(1, 2, 3);
}
Eclipse will complain and say that "The method MethodA(int, int, int) in the type A is not applicable for the arguments (int, int)."
But why? I've already implemented interface B. Shouldn't MethodA(int, int, int) have overload MethodA(int, int), making MethodA able to accept three integers as well?
The above looks a little confused.
You need to specify your return types, specify names for each argument (even in the interface) and declare the implemented methods as public eg.
public int MethodA(int a, int b, int c)
{
//Actual implementation e.g.
return 0;
}
Your static main() method has to reside within a class (e.g. the Foo class above), and finally call the method with real arguments.
Once you've done that, then all should be good. You can certainly provide overloading as in the above. You just need to resolve the more basic issues first. I would get a very basic single method going, and then enhance from there in order to get something working.
I am having a base class C with fields X, Y and Z.
C1 extends C and is having an extra field, T.
In the C1 constructor, I do call the super (C) constructor with some hard coded values for the fields X, Y and Z. Then I set T.
Are there any patterns to automatically validate all the fields of C1 by doing something in the C constructor ? So I am trying to push the automatic validation to the base class.
Please note that calling the super constructor should be done before any statement in the C1 constructor. I started with some abstract validate() method, but I am not I am on the right track.
Thanks.
As a matter of principle, C should not know about C1's properties, because C1 is a specialization of C. However, what you can do is make an abstract validate() method in C, that must be implemented by C1. Then, in C's constructor, you can call the abstract method. Since, C1 will have to implement the validate(), it can then add it's property/field validation there.
Although it is against all OO principles, you could take advantage of Java's reflection property. Via reflection you can find out which methods and fields a class has. So you could pass the subclass object to the base class and the base class could check for all fields and validate them. If you do this at the end of the subclass constructor, you could let the validation method return a value to see if the values are valid or not.
I want to state that I don't think it's the right way to go but it should work
I would say that the super class should validate itself. An object needs to enforce its own contract. Any validation of C's values should be done in its own constructor. Likewise, the subclass should validate itself.
public class A {
private int x;
public A(int x) {
if (x < 0) throw new IllegalArgumentException("x cannot be negative");
this.x = x;
}
}
public class B extends A {
private String y;
public B(int x, String y) {
super(x);
if (y == null) throw new IllegalArgumentException("y cannot be null");
this.y = y;
}
}
class C{
Object x, y, z;
public C(Object x, Object y, Object z){
this.x = x;
this.y = y;
this.z = z;
}
public boolean validate(){ /**do stuff**/}
}
class D{
public D(/**args**/){
super(/**args**/);
if(validate()){
/**do stuff**//
}
}
}