This question already has answers here:
Using inherited overloaded methods
(11 answers)
Closed 7 years ago.
The code I am running is as follows :
public class Triangle {
public void draw() {
System.out.println("Base::draw\n");
}
public void computeCentroid(Triangle t) {
System.out.println("Base::centroid");
}
}
class RightAngledTr extends Triangle {
public void draw() {
System.out.println("RightAngle::draw\n" );
}
public void computeCentroid(RightAngledTr t) {
System.out.println("RtAngle::centroid");
}
}
public static void main(String[] args) {
Triangle tr= new RightAngledTr();
RightAngledTr rtr= new RightAngledTr();
tr.computeCentroid(tr);
tr.draw();
tr.computeCentroid(rtr);
}
The output this gives is as follows :
Base::centroid
RightAngle::draw
Base::centroid
I don't understand the reason behind the third output line.
My doubt :
tr.computeCentroid(rtr) should call the method of Derived class RightAngledTr(since the parameter passed is rtr). Hence print : RtAngle::centroid
Please help me out here. Thanks in advance!
public void computeCentroid(RightAngledTr t)
and
public void computeCentroid(Triangle t)
have different method signatures, so there is no override here, at all.
Class RightAngledTr does not override the method but overload since Java method is invariant.
Class RightAngledTr has 2 methods essentially, one requiring Triangle and the other RightAngledTr) so by specifying the most specific parameter, the JVM knows which methods to invoke by matching the parameter type to the most specific method matching it.
See more:
JLS 15.12.2.5. Choosing the Most Specific Method
For RightAngledTr.computeCentroid to override Triangle.computeCentroid it must have a matching parameter declaration. But yours does not. If you change your declaration in RightAngledTr to:
#Override
public void computeCentroid(Triangle t)
Then you will see the behavior you expect. Note the use of #Override, which will help you identify this issue in the future.
Related
I have created a simple interface using java8. In that it contains one method and one default method.
interface Lambda{
default void dummy(){
System.out.println("Call this..");
}
void yummy();
}
I'm trying to us these two methods using the historical way like
public class DefaultCheck {
public static void main(String[] args) {
DefaultCheck check = new DefaultCheck();
check.activate(new Lambda() {
#Override
public void yummy() {
dummy();
}
});
}
void activate(Lambda lambda){
lambda.yummy();
}
}
Now i'm trying to implement the same thing using lambda expression, getting error like `dummy is undefined`
check.activate(() -> {
dummy();
});
Can any one please suggest, how to implement this scenario using Lambda expression ??
It can't be done.
JLS 15.27.2 addresses this:
Unlike code appearing in anonymous class declarations, the meaning of
names and the this and super keywords appearing in a lambda body,
along with the accessibility of referenced declarations, are the same
as in the surrounding context (except that lambda parameters introduce
new names).
The transparency of this (both explicit and implicit) in the body of a
lambda expression - that is, treating it the same as in the
surrounding context - allows more flexibility for implementations, and
prevents the meaning of unqualified names in the body from being
dependent on overload resolution.
Practically speaking, it is unusual for a lambda expression to need to
talk about itself (either to call itself recursively or to invoke its
other methods), while it is more common to want to use names to refer
to things in the enclosing class that would otherwise be shadowed
(this, toString()). If it is necessary for a lambda expression to
refer to itself (as if via this), a method reference or an anonymous
inner class should be used instead.
The inner class implementation works since the code is called as if you coded:
check.activate(new Lambda() {
#Override
public void yummy() {
this.dummy();
}
});
Our problem now is that lambdas do not introduce a new scope. So, if you want your lambda to be able to reference itself, you may refine your #FunctionalInterface so that its functional method accepts itself and its required parameters:
check.activate(this_ -> this_.dummy());
where Lambda is defined as:
#FunctionalInterface
public interface Lambda {
void yummy(Lambda this_);
default void yummy() {
yummy(this);
}
default void dummy(){
System.out.println("Call this..");
}
}
If I understand it correctly. You are trying to call a default method in an interface through lambda implementation. I think it can be done.
#FunctionalInterface
interface Value
{
String init(Value a);
default String add(String b)
{
return "added content "+b;
}
default String getResult()
{
String c = init(this);
return c;
}
}
public class Main
{
public static void main(String[] args)
{
Value v = a -> a.add("inpout"); // here I am calling add method in Value interface.
String c = v.getResult();
System.out.println(c);
}
}
I have created a simple interface using java8. In that it contains one method and one default method.
interface Lambda{
default void dummy(){
System.out.println("Call this..");
}
void yummy();
}
I'm trying to us these two methods using the historical way like
public class DefaultCheck {
public static void main(String[] args) {
DefaultCheck check = new DefaultCheck();
check.activate(new Lambda() {
#Override
public void yummy() {
dummy();
}
});
}
void activate(Lambda lambda){
lambda.yummy();
}
}
Now i'm trying to implement the same thing using lambda expression, getting error like `dummy is undefined`
check.activate(() -> {
dummy();
});
Can any one please suggest, how to implement this scenario using Lambda expression ??
It can't be done.
JLS 15.27.2 addresses this:
Unlike code appearing in anonymous class declarations, the meaning of
names and the this and super keywords appearing in a lambda body,
along with the accessibility of referenced declarations, are the same
as in the surrounding context (except that lambda parameters introduce
new names).
The transparency of this (both explicit and implicit) in the body of a
lambda expression - that is, treating it the same as in the
surrounding context - allows more flexibility for implementations, and
prevents the meaning of unqualified names in the body from being
dependent on overload resolution.
Practically speaking, it is unusual for a lambda expression to need to
talk about itself (either to call itself recursively or to invoke its
other methods), while it is more common to want to use names to refer
to things in the enclosing class that would otherwise be shadowed
(this, toString()). If it is necessary for a lambda expression to
refer to itself (as if via this), a method reference or an anonymous
inner class should be used instead.
The inner class implementation works since the code is called as if you coded:
check.activate(new Lambda() {
#Override
public void yummy() {
this.dummy();
}
});
Our problem now is that lambdas do not introduce a new scope. So, if you want your lambda to be able to reference itself, you may refine your #FunctionalInterface so that its functional method accepts itself and its required parameters:
check.activate(this_ -> this_.dummy());
where Lambda is defined as:
#FunctionalInterface
public interface Lambda {
void yummy(Lambda this_);
default void yummy() {
yummy(this);
}
default void dummy(){
System.out.println("Call this..");
}
}
If I understand it correctly. You are trying to call a default method in an interface through lambda implementation. I think it can be done.
#FunctionalInterface
interface Value
{
String init(Value a);
default String add(String b)
{
return "added content "+b;
}
default String getResult()
{
String c = init(this);
return c;
}
}
public class Main
{
public static void main(String[] args)
{
Value v = a -> a.add("inpout"); // here I am calling add method in Value interface.
String c = v.getResult();
System.out.println(c);
}
}
I am newbie to java, and developing a real life project. I have many methods and about 2500 lines of code thus far. Many of the methods are slightly different(usually a difference of mere a single identifier) due to which i have to copy the code again and again with slight changes.
What i want is to pass a method as parameter to another method, I've gone through lambda expressions
but i could not find it enough appealing, off-course due to my own conceptual shortcomings. because it tells to define functional interface of each method to be passed. but as per my thoughts it would not give me a generic code so that i would be able to simply add some other Tables in future.
i am putting a piece of code to demonstrate and better explain my problem.
if(houseTabPanel.getComponentCount()==0){
houseTableDb();
}
if(isSelected){
selection(houseTable);
}
else {
houseTable.setColumnSelectionAllowed(false);
houseTable.setRowSelectionAllowed(false);
houseTable.setCellSelectionEnabled(false);
Rselection(houseTable);
}
now i have different methods named houseTableDb() , plotTableDb() , adminTableDb() etc.
i want to make a method of this piece of code and pass plotTableDb() etc as parameter..
something like...
public void genericMethod(JPanel p, JTable t, some method reference to use instead of houseTableDb){}
pardon me if am not descriptive enough.. any response would be truly appreciated by core of the heart.
Provided that all of these methods have the same signature you can define an interface with a single method with that signature (return value, parameter list). Then you write classes implementing the method, one for each method's implementation. For passing the method, you create an object of that class and pass the object. The call to the actual method is replaced by the call to the method defined in the interface.
interface Callee {
void meth();
}
class MethOne implements Callee {
public void meth(){...}
}
void caller( Callee callee ){
callee.meth();
}
Callee ofOne = new MethOne();
caller( ofOne );
But to avoid all this hazzle: that's why lambdas have been added...
You can do like this :
public void genericMethod(JPanel p, JTable t, TableDbCallBack tableDb)
{
if(p.getComponentCount()==0)
{
tableDb.run();
}
if(isSelected)
{
selection(t);
}
else
{
t.setColumnSelectionAllowed(false);
t.setRowSelectionAllowed(false);
t.setCellSelectionEnabled(false);
Rselection(t);
}
}
usage :
genericMethod(p, t, new HouseTableDb());
genericMethod(p, t, new AdminTableDb());
Implementation :
public interface TableDbCallBack extends Runnable {}
public class HouseTableDb implements TableDbCallBack
{
#Override
public void run()
{
// Whatever it should do
}
}
public class AdminTableDb implements TableDbCallBack
{
#Override
public void run()
{
// Whatever it should do
}
}
This question already has answers here:
What's wrong with overridable method calls in constructors?
(8 answers)
Closed 5 years ago.
Let's suppose I have an abstract Base class that implements Runnable interface.
public abstract class Base implements Runnable {
protected int param;
public Base(final int param) {
System.out.println("Base constructor");
this.param = param;
// I'm using this param here
new Thread(this).start();
System.out.println("Derivative thread created with param " + param);
}
#Override
abstract public void run();
}
And here is one of a few derivative classes.
public class Derivative extends Base {
public Derivative(final int param) {
super(param);
}
#Override
public void run() {
System.out.println("Derivative is running with param " + param);
}
public static void main(String[] args) {
Derivative thread = new Derivative(1);
}
}
The point is that I want my Base class do some general stuff instead of copying it every time.
Actually, it's running fine, the output is always the same:
Base constructor
Derivative thread created with param 1
Derivative is running with param 1
But is it safe IN JAVA to start a thread calling the abstract method in constructor? Because, in C++ and C# it is unsafe in most cases, so far as I know.
Thank you!
This code demonstrates why you should never call an abstract method, or any other overridable method, from a constructor:
abstract class Super {
Super() {
doSubStuff();
}
abstract void doSubStuff();
}
class Sub extends Super {
String s = "Hello world";
void doSubStuff() {
System.out.println(s);
}
}
public static void main(String[] args) {
new Sub();
}
When run, this prints null. This means the only "safe" methods to have in a constructor are private and/or final ones.
On the other hand, your code doesn't actually call an abstract method from a constructor. Instead, you pass an uninitialized object to another thread for processing, which is worse, since the thread you're starting may be given priority and execute before your Base finishes its initialization.
Not a good idea since when run() is invoked, the Derivative object may not have been initialized. If run() depends on any state in Derivative, it can fail.
In your simple case it works. But then there's no point for the subclass. You can simply
public Base(final int param, Runnable action) {
new Thread(action).start();
It's a very bad practice to call an abstract method from a constructor. Methods called from constructors should always be private or final, to prevent overriding.
See this link to a question here
Passing this out of the constructor is called "letting this escape from the constructor", and can lead to some particularly nasty and weird bugs, because the object may be in an inconsistent state.
This is especially the case when this is passed to another thread, as in this example. Due to the JVMs right to reorder statements within a thread, you can get undefined behaviour/state occurring.
I'm tring to find out a way to get the complete method signature that is calling me.
For example:
public class Called {
public void whoCallMe() {
System.out.println("Caller Method: " + new Throwable().getStackTrace()[1].getMethodName());
}
}
public class Caller {
public static void run(int i) {
new Called().whoCallMe();
}
public static void run(String str) {
new Called().whoCallMe();
}
public static void run(boolean b) {
new Called().whoCallMe();
}
/** MAIN **/
public static void main(String[] args) {
run("hi");
}
The way I've implemented whoCallMe() method I can see that run method called it, but since I 3 overloads I can't say which one was the caller cause whoCallme return only "run" as the method name.
Do you guys know other way where I could get the complete method signature like run(java.lang.String) ?
You can use AspectJ to create an aspect which will apply to every method invocation and add the details about the method being invoked to a per-thread stack, and then remove it after method completes. It's going to be insanely expensive, of course. Most likely you don't want to do that. Also you don't want to throw anything to find out who called you.
Basically the answer to your question is: do not do it.
Explain why you think you want to do it and somebody will give you a good alternative.
Also, come to think of it, you can argue that method overloading (not overriding!) is considered harmful. Do you really need multiple different methods with different arguments and the same name?