The following example is a reduction of the real problem in that it tries to simplify is as much as possible.
I have a java interface, and several objects that implement that interface, like:
public interface Shape{
public void draw();
public void erase();
public boolean isDrawn();
}
public class Square implements Shape{
#Override
public void draw(){
//TODO: method implementation
}
#Override
public void erase(){
//TODO: method implementation
}
Override
public boolean isDrawn(){
//TODO: method implementation
return false;
}
}
public Triangle implements Shape{
//same as above
}
public Circle implements Shape{
//same as above
}
This is the structure of my program. By using AspectJ I want to have a map that holds each object that implements the interface. To do so I was trying to capture the constructors by using the following aspect:
public aspect ShapeHolderAspect{
private Map<Integer, Shape> map = new HashMap<>();
private int count = 0;
pointcut shapeInit(): call((Shape+).new(..));
Object around(): shapeInit() {
System.out.println("capturing new");
Shape shapeType = (Shape)proceed();
map.put(++count, shapeType);
return shapeType;
}
}
This code will work if I create a Shape using the following scenario:
public static void main(String[] args){
Shape myShape = new Circle();
}
However, I am using java language reflection, and so technically I don't call the "new" constructor. Instead I locate the path of the package, and create the object passing a string with the name of the class:
public static void main(String[] args){
String shapeClassName = args[0];
Class<?> classType = Class.forName("myPackage.figures" + "." + shapeClassName);
Shape myShape =(Shape)classType.getConstructor().newInstance();
}
By doing this way, AspectJ cannot detect that I am creating shapes. How do I fix this?
New, better version:
Well, while the old version below actually catches all constructor executions, an around advice on constructor execution returns null because the object in question has not been initialised yet. So you would end up with a map of null pointers in your aspect. In order to fix this you need to bind this() to a variable (sample code uses default package name):
public class Application {
public static void main(String[] args) throws Exception {
new Circle().draw();
((Shape) Class.forName("Triangle").getConstructor().newInstance()).isDrawn();
((Shape) Class.forName("Square").getConstructor().newInstance()).erase();
}
}
import java.util.HashMap;
import java.util.Map;
public aspect ShapeHolderAspect {
private Map<Integer, Shape> map = new HashMap<Integer, Shape>();
private int count = 0;
after(Shape shape): execution(Shape+.new(..)) && this(shape) {
System.out.println(thisJoinPointStaticPart);
map.put(++count, shape);
}
after() : execution(* Application.main(..)) {
System.out.println("\nList of shapes:");
for (int key : map.keySet())
System.out.println(" " + key + " -> " + map.get(key));
}
}
The output looks like this:
initialization(Circle())
initialization(Triangle())
initialization(Square())
List of shapes:
1 -> Circle#1a2961b
2 -> Triangle#12d03f9
3 -> Square#5ffb18
BTW, if you absolutely need an around advice because you want to do other things before and after object creation, it would look like this:
void around(Shape shape): execution(Shape+.new(..)) && this(shape) {
System.out.println(thisJoinPointStaticPart);
proceed(shape);
map.put(++count, shape);
}
Old, incomplete version:
Quite simply, just intercept constructor execution instead of call:
pointcut shapeInit(): execution(Shape+.new(..));
This way you weave into the called code (callee), not the calling code (caller). Consequently, it does not matter if the caller issues a reflective or normal call.
Found that the following pointcut will do the job:
pointcut lockReflectInit(): call(public Object java.lang.reflect.Constructor.newInstance(..));
This will however catch ALL calls of newInstance, and not just the ones that return Shape =(
Related
I would like to be able to provide a functional interface that accepts several different types of lambda functions.
I read this. The first answer to this question clarifies why overloading an abstract method in a functional interface could cause undefined behavior. However, is there a way to do the equivalent of overloading an abstract method in a functional interface if I supply all of the defaults?
I would like to be able to write something like the following code:
Ball b = () -> System.out.println("You hit it!");
Ball ba = (boolean miss) -> System.out.println(miss);
b.hit();
b.hit(false);
ba.hit();
ba.hit(false);
The desired result would be:
You hit it!
default false
default hit
false
Consider the following (non-compilable) code (mostly copied from the linked question):
#FunctionalInterface
public interface Ball
{
void hit();
void hit(boolean miss);
default void hit(){
System.out.println("default hit");
}
default void hit(boolean miss){
System.out.println("default" + miss);
}
}
I am looking for an alternative to this code that would compile.
You could wrap the interface in a class and then pass on the method calls to the interfaces internally.
Example code:
public class Test{
public static void main(String... args) throws Exception{
Ball b = new Ball(() -> System.out.println("You hit it!"));
Ball ba = new Ball((boolean miss) -> System.out.println(miss));
b.hit();
b.hit(false);
ba.hit();
ba.hit(false);
}
public static class Ball{
final Hit a;
final HitBoolean b;
public Ball(Hit a){
this.a = a;
b = (miss) -> System.out.println("default " + miss);
}
public Ball(HitBoolean b){
this.b = b;
a = () -> System.out.println("default hit");
}
public void hit(){
a.hit();
}
public void hit(boolean miss){
b.hit(miss);
}
}
public interface Hit{
void hit();
}
public interface HitBoolean{
void hit(boolean miss);
}
}
Output of the program:
You hit it!
default false
default hit
false
You could do something like this. But you would need to name your variables properly to keep track of both the arg and the consumer that takes it.
#FunctionalInterface
interface Ball<T> {
void hit();
static <T> Ball<T> withArg(T arg, Consumer<T> com) {
return () -> com.accept(arg);
}
}
public class Demo {
public static void main(String[] args) {
Ball<Boolean> b = () -> System.out.println("You Hit it!");
b.hit();
Ball<Boolean> ba = Ball.withArg(false, a -> System.out.println(a));
Ball<Boolean> bb = Ball.withArg(true, a -> System.out.println(a));
ba.hit();
bb.hit();
}
}
first thing about functional interface is , it can have only one abstract method.In that case you cant even think of the second method (let it be abstract method too). you can have any number of default methods.
So answer is 100% not possible and Your code above will get compilation error as you kept #FunctionalInterface annotation which strictly prohibits keeping more than one abstract method.
As per your code
#FunctionalInterface
public interface MyInter {
public abstract void fly();
public abstract void fly(int a);
default void fly() {} \\line1
default void fly(int g) { } \\line2
}
line 1 and 2 will throw compile time error as java sees them by method name are same and argument types are same , they will never bother of return type or default or etc..(primary rule of overloading).
more over if remove line 1 and 2 , then too code will throw error because #functionalinterface will give compilation error stating invalid '#FunctionalInterface' annotation; MyInter is not a functional interface .
Hope this answers your question...
Is there a way to cast an Object to its "lowest" class? In my case, "Arc" and "Line" extend "Curve". I want to save both in an ArrayList and then do something with them, depending on what class it is. This example outputs "curve", "curve" but I want it to be "arc", "line". Thanks for your help!
public class Test4 {
public static void main(String[] args) {
ArrayList<Curve> curves = new ArrayList<>();
Arc arc = new Arc(new Point(0, 0, 0), 0, 0, 0);
Line line = new Line(new Point(0, 0, 0), new Point(1, 0, 0));
curves.add(arc);
curves.add(line);
for (Curve i : curves) {
test(i);
}
}
public static void test(Line l) {
System.out.println("line");
}
public static void test(Arc a) {
System.out.println("arc");
}
public static void test(Curve c) {
System.out.println("curve");
}
}
EDIT: Thank you for your answers! It works so far, but my problem is a little more complicated. What I want to do is find the intersection Point(s) of two geometrical Objects (so Line - Arc, Line - Line, Line - Circle etc.)
public class Line{
//constructor and other methods
public Point[] intersection(Circle circle) {
//some code
}
public Point[] intersection(Line line) {
//some code
}
public Point[] intersection(LineSeg s) {
//some code
}
}
I want to access these methods with Curve objects, so in abstract class Curve there is a method intersection (Curve). When I call this method it returns an empty Array, because it called the method from Curve class. How can I tell Java to use the methods from classes Arc, Line etc and not from Curve?
public abstract class Curve {
public Point[] intersection(Curve c) {
return new Point[] {};
}
}
Method overloading is resolved during compilation, based on the static type of the parameters passed to the method, therefore, when you pass a variable of type Curve, the method static void test(Curve c) is always chosen, regardless of the runtime type of the objects referenced by the variable i.
You can replace your static test methods with instance methods, and thus use method overriding:
In Line class:
public void test() {
System.out.println("line");
}
In Arc class:
public void test() {
System.out.println("arc");
}
In Curve class:
public void test() {
System.out.println("curve");
}
And change your loop to
for (Curve i : curves) {
i.test();
}
That's the most common design error you are making there.
As #Eran said you shall move the logic from global handler into the class instances.
The problem can be specified in another way:
You cast object like Arc and Line to its more generic form - Curve
And then try to differentiate between Arc and Line objects.
For Arcs output message that the object is Arc
For Lines output message that the object is Line
To differentiate the object classes you must use Java mechanisms:
Execute its method (methods of objects are the best way to determine the type of object)
Use instenaceof operator
So the best, proffesional approach is to implement methods test in each of the classes:
public void test() {
System.out.println("Your type");
}
It's not advised to use instanceof because it generate bugs and you can write a code like this one:
public static void test(Curve c) {
if(c instanceof Arc) {
System.out.println("Arc");
return;
}
System.out.println("Something else");
}
In that case if you add new class like OtherGeometricalObject you may forget to change implementation of test to add line:
if(c instanceof OtherGeometricalObject) {
System.out.println("OtherGeometricalObject");
return;
}
That's why instanceof is in most cases a really bad deal and should be avoided!
If you would like to differentiate between objects like in the example
(do something for objects of one class and something other for other classes objects)
just use class method!
It's the mechnism designed for that purpose!
I hope my explanation is rich and helpful :)
You want to get a OOP behavior for each subclass where the behavior depends on the runtime class but overloading with a static modifier will not allow that.
The selection of the method being done at compile time according to the declared type of the argument.
As Eran suggested, let each subclass defines its test() method and invoke the method on an instance of it.
Besides, what you want can be performed with an Object method.
The method toString() is designed for returning a String representing of the object.
You can directly use it in this way :
for (Curve curve : curves) {
System.out.println(curve);
}
If the default toString() method doesn't suit for you, you may
override it in subclasses.
In Line class :
public String toString() {
return "line";
}
In Arc class:
public String toString() {
return "arc";
}
In Curve class:
public String toString() {
return "curve";
}
I searched the whole StackOverflow website I come across only one nearest
answer but not working in my condition.
How can I call methods of two classes in each other
First Class is Alpha and calling a Function of Beta
public Class Alpha
{
Beta obj;
public Alpha()
{
obj = new Beta();
}
public void A()
{
print A;
obj.B();
}
}
Second Class is Beta and calling a function of Alpha
public Class Beta
{
Alpha obj;
public Beta()
{
obj = new Alpha();
}
public void B()
{
print B;
obj.A()
}
}
In Java/android, it shows StackOverflow exception. Due to the recursive call of constructors of each other.
How to avoid this Exception?
I have 15 Classes and each one is linked Cyclically.
Do I need to use parent class?
Or How I should use constructors to avoid StackOverflow Exception?
Here's a suggestion that will break the cycle: Specify one class as the parent and the other as the dependent.
Let's put Alpha in charge:
public class Alpha {
private Beta beta;
public Alpha() {
this.beta = new Beta(this);
}
}
Here's the child Beta:
public class Beta {
private Alpha alpha;
public Beta(Alpha parent) {
this.alpha = parent;
}
}
No more cycle.
You shall change your class Beta's definition to break the circular link between the two classes and creating their instances. It could be somewhat like this instead:
public class Beta {
Alpha obj;
public Beta() {
}
public void B() {
print B;
new Alpha().A();
}
}
Ideally, you shall not create instances of other classes unless you would want to access them.
The stack overflow is obvious; it's not just that the class definitions are cyclical; the constructors are recursive. The recursion is just "hidden" because they are in different classes. With any recursion, there must be some limit condition to break the recursion cycle. Without knowing the details of your problem -- why do you have this cyclical definition -- it's hard to give a solution. It really comes down to a question of code architecture. I can offer a few suggestions.
First, I generally dislike cyclical definitions. It leads to confusion and issues in doing code builds and ports. This can be avoided by using interfaces; maybe an empty marker interface. I would then take assignment of the internal objects out of the constructor, and make an explicit set() function, so that the caller has to initialize these:
public interface SomeInterface { }
public class Alpha implements SomeInterface
{
private SomeInterface obj;
public Alpha()
{}
public void setBeta (SomeInterface si)
{
obj = si;
}
}
public class Beta implements SomeInterface
{
private SomeInterface obj;
public Beta ()
{ }
public void setAlpha ( SomeInterface si )
{
obj = si;
}
}
In the calling code, you would have
Alpha a = new Alpha();
a.setBeta ( new Beta() );
In JavaScript one can create and edit an object's functions on the fly. Is this possible with a Java object's methods? I am essentially wanting something like this:
public class MyObject{
private int x;
public MyObject(){x = 0;}
public myMethod(){}
}
MyObject foo = new MyObject();
and later call something along the lines of:
foo.myMethod = new method({x = 42;});
It's not directly possible, but you could try something like this:
public class MyObject {
private int x;
interface MyMethod {
void call();
}
public MyObject() {
x = 0;
}
public MyMethod myMethod = new MyMethod() {
#Override
public void call() {
x = 42;
}
};
}
You can't edit it in the way that you are trying to demonstrate above, the closest thing you could do to emulate it would be to intercept the method. The only way I could think of at the current moment is to use a MethodInterceptor found within the cglib library to intercept the method.
In Java you cannot do this like you would do it in Javascript.
But in Java you can achieve such an behavior using the Strategy pattern.
For example,
public interface Strategy {
void doSomething(MyObject obj);
}
public class BasicStrategy implements Strategy {
public void doSomething(MyObject obj) {
//do something
}
}
public class AnotherStrategy implements Strategy {
public void doSomething(MyObject obj) {
obj.setX(42);
}
}
public class MyObject {
private Strategy actualStrategy = new BasicStrategy();
private int x = 0;
public void executeStrategy() {
actualStrategy.doSomething(this);
}
public void setStrategy(Strategy newStrategy) {
actualStrategy = newStrategy;
}
public void setX(int x) {
this.x = x;
}
}
You can alter the behavior of the method at runtime using the following code.
MyObject obj = new MyObject();
obj.setStrategy(new AnotherStrategy());
obj.executeStrategy();
Yes, it's theoretically possible, but you don't want to do it. This sort of thing is black magic, and if you need to ask the question, you're several years from being ready to work with it.
That said, what you're trying to accomplish may be workable with the Strategy design pattern. The idea here is that you define an interface that has the method(s) you need to swap out (say, calculate()), and the class whose behavior you want to change has a field of that interface. You can then modify the contents of that field.
public interface Calculator {
double calculate(double x, double y);
}
public class MathStuff {
private Calculator calc;
...
public void doStuff() {
...
result = calc.calculate(x, y);
...
}
}
public class Add implements Calculator {
public double calculate(double x, double y) {
return x + y;
}
}
You cannot do this. In java new method is made to return the instance of class Object, not methods. And one thing is to understand is Javascript is an functional programming language and Java is a object oriented language. You cannot treat a method as object in java, also it breaks the security of java encapsulation.
So, in a single parent inheritance model what's the best solution for making code extensible for future changes while keeping the same interface (I'd like to emphasize the fact that these changes cannot be known at the time of the original implementation, the main focus of my question is to explore the best mechanism/pattern for supporting these changes as they come up)? I know that this is a very basic OO question and below I provide example of how I've been going about it, but I was wondering if there a better solution to this common problem.
Here's what I've been doing (the example code is in Java):
In the beginning, the following two classes and interface are created:
public class Foo
{
protected int z;
}
public interface FooHandler
{
void handleFoo(Foo foo);
}
public class DefaultFooHandler implements FooHandler
{
#Override
public void handleFoo(Foo foo)
{
//do something here
}
}
The system uses variables/fields of type FooHandler only and that object (in this case DefaultFooHandler) is created in a few, well-defined places (perhaps there's a FooHandlerFactory) so as to compensate for any changes that might happen in the future.
Then, at some point in the future a need to extend Foo arises to add some functionality. So, two new classes are created:
public class ImprovedFoo extends Foo
{
protected double k;
}
public class ImprovedFooHandler extends DefaultFooHandler
{
#Override
public void handleFoo(Foo foo)
{
if(foo instanceof ImprovedFoo)
{
handleImprovedFoo((ImprovedFoo)foo);
return;
}
if(foo instanceof Foo)
{
super.handleFoo(foo);
return;
}
}
public void handleImprovedFoo(ImprovedFoo foo)
{
//do something involving ImprovedFoo
}
}
The thing that makes me cringe in the example above is the if-statements that appear in ImprovedFooHandler.handleFoo
Is there a way to avoid using the if-statements and the instanceof operator?
First of all the code you wrote won't work.
Each time you see instanceof and if...else together be very careful. The order of these checks is very important. In your case you'll never execute handleImpovedFoo. Guess why :)
It's absolutely normal you have these instanceof statements. Sometimes it's the only way to provide different behavior for a subtype.
But here you can use another trick: use simple Map. Map classes of foo-hierarchy to instances of fooHandler-hierarchy.
Map<Class<? extends Foo>, FooHandler> map ...
map.put( Foo.class, new FooHandler() );
map.put( ImprovedFoo.class, new ImprovedFooHandler() );
Foo foo ...; // here comes an unknown foo
map.get( foo.getClass() ).handleFoo( foo );
The best way of handling this depends too much on the individual case to provide a general solution. So I'm going to provide a number of examples and how I would solve them.
Case 1: Virtual File System
Clients of your code implement virtual file systems which enable them to operate any sort of resource which can be made to look like a file. They do so by implementing the following interface.
interface IFolder
{
IFolder subFolder(String Name);
void delete(String filename);
void removeFolder(); // must be empty
IFile openFile(String Name);
List<String> getFiles();
}
In the next version of your software you want to add the ability to remove a directory and all it contents. Call it removeTree. You cannot simply add removeTree to IFolder because that will break all users of IFolder. Instead:
interface IFolder2 implements IFolder
{
void removeTree();
}
Whenever a client registers an IFolder (rather then IFolder2), register
new IFolder2Adapter(folder)
Instead, and use IFolder2 throughout your application. Most of your code should not be concerned with the difference about what old versions of IFolder supported.
Case 2: Better Strings
You have a string class which supports various functionality.
class String
{
String substring(int start, end);
}
You decide to add string searching, in a new version and thus implement:
class SearchableString extends String
{
int find(String);
}
That's just silly, SearchableString should be merged into String.
Case 3: Shapes
You have a shape simulation, which lets you get the areas of shapes.
class Shape
{
double Area();
static List<Shape> allShapes; // forgive evil staticness
}
Now you introduce a new kind of Shape:
class DrawableShape extends Shape
{
void Draw(Painter paint);
}
We could add a default empty Draw method to Shape. But it seems incorrect to have Shape have a Draw method because shapes in general aren't intended to be drawn. The drawing really needs a list of DrawableShapes not the list of Shapes that is provided. In fact, it may be that DrawableShape shouldn't be a Shape at all.
Case 4: Parts
Suppose that we have a Car:
class Car
{
Motor getMotor();
Wheels getWheels();
}
void maintain(Car car)
{
car.getMotor().changeOil();
car.getWheels().rotate();
}
Of course, you know somewhere down the road, somebody will make a better car.
class BetterCar extends Car
{
Highbeams getHighBeams();
}
Here we can make use of the visitor pattern.
void maintain(Car car)
{
car.visit( new Maintainer() );
}
The car passes all of its component parts to calls into ICarVisitor interface allowing the Maintainer class to maintain each component.
Case 5: Game Objects
We have a game with a variety of objects which can be seen on screen
class GameObject
{
void Draw(Painter painter);
void Destroy();
void Move(Point point);
}
Some of our game objects need the ability to perform logic on a regular interval, so we create:
class LogicGameObject extends GameObject
{
void Logic();
}
How do we call Logic() on all of the LogicGameObjects? In this case, adding an empty Logic() method to GameObject seems like the best option. Its perfectly within the job description of a GameObject to expect it to be able to know what to do for a Logic update even if its nothing.
Conclusion
The best way of handling this situations depends on the individual situation. That's why I posed the question of why you didn't want to add the functionality to Foo. The best way of extending Foo depends on what exactly you are doing. What are you seeing with the instanceof/if showing up is a symptom that you haven't extended the object in the best way.
In situations like this I usually use a factory to get the appropriate FooHandler for the type of Foo that I have. In this case there would still be a set of ifs but they would be in the factory not the implementation of the handler.
Yes, don't violate LSP which is what you appear to be doing here. Have you considered the Strategy pattern?
This looks like a plain simple case for basic polymorphism.Give Foo a method named something like DontWorryI'llHandleThisMyself() (um, except without the apostrophe, and a more sensible name). The FooHandler just calls this method of whatever Foo it's given. Derived classes of Foo override this method as they please. The example in the question seems to have things inside-out.
With the visitor pattern you could do something like this,
abstract class absFoo {}
class Foo extends absFoo
{
protected int z;
}
class ImprovedFoo extends absFoo
{
protected double k;
}
interface FooHandler {
void accept(IFooVisitor visitor, absFoo foo);
}
class DefaultFooHandler implements FooHandler
{
public void accept(IFooVisitor visitor, absFoo foo)
{
visitor.visit(this, foo);
}
public void handleFoo(absFoo foo) {
System.out.println("DefaultFooHandler");
}
}
class ImprovedFooHandler implements FooHandler
{
public void handleFoo(absFoo foo)
{
System.out.println("ImprovedFooHandler");
}
public void accept(IFooVisitor visitor, absFoo foo) {
visitor.visit(this, foo);
}
}
interface IFooVisitor {
public void visit(DefaultFooHandler fooHandler, absFoo foo);
public void visit(ImprovedFooHandler fooHandler, absFoo foo);
}
class FooVisitor implements IFooVisitor{
public void visit(DefaultFooHandler fHandler, absFoo foo) {
fHandler.handleFoo(foo);
}
public void visit(ImprovedFooHandler iFhandler, absFoo foo) {
iFhandler.handleFoo(foo);
}
}
public class Visitor {
public static void main(String args[]) {
absFoo df = new Foo();
absFoo idf = new ImprovedFoo();
FooHandler handler = new ImprovedFooHandler();
IFooVisitor visitor = new FooVisitor();
handler.accept(visitor, idf);
}
}
But this does not guarantee only Foo can be passed to DefaultFooHandler. It allows ImprovedFoo also can be passed to DefaultFooHandler. To overcome, something similar can be done
class Foo
{
protected int z;
}
class ImprovedFoo
{
protected double k;
}
interface FooHandler {
void accept(IFooVisitor visitor);
}
class DefaultFooHandler implements FooHandler
{
private Foo iFoo;
public DefaultFooHandler(Foo foo) {
this.iFoo = foo;
}
public void accept(IFooVisitor visitor)
{
visitor.visit(this);
}
public void handleFoo() {
System.out.println("DefaultFooHandler");
}
}
class ImprovedFooHandler implements FooHandler
{
private ImprovedFoo iFoo;
public ImprovedFooHandler(ImprovedFoo iFoo) {
this.iFoo = iFoo;
}
public void handleFoo()
{
System.out.println("ImprovedFooHandler");
}
public void accept(IFooVisitor visitor) {
visitor.visit(this);
}
}
interface IFooVisitor {
public void visit(DefaultFooHandler fooHandler);
public void visit(ImprovedFooHandler fooHandler);
}
class FooVisitor implements IFooVisitor{
public void visit(DefaultFooHandler fHandler) {
fHandler.handleFoo();
}
public void visit(ImprovedFooHandler iFhandler) {
iFhandler.handleFoo();
}
}
public class Visitor {
public static void main(String args[]) {
FooHandler handler = new DefaultFooHandler(new Foo());
FooHandler handler2 = new ImprovedFooHandler(new ImprovedFoo());
IFooVisitor visitor = new FooVisitor();
handler.accept(visitor);
handler2.accept(visitor);
}
}