Passing Parameters In Abstract Method - java

I have an abstract class in Java that has this method called
public abstract void onImageRendered(BufferedImage render)
I want the user to access the rendered image with this method. I have another method called
public void render()
That renders the image. The buffered image in the abstract method should not be any image but the rendered image from this method.
How do I pass the rendered image from that method as the parameter of the abstract method?
Here is my code:
public static void render(Scene scene) throws MORISIllegalMethodCallException{
if(propertiesAreSet){
Camera activeCamera = scene.getActiveCamera();
for (int x = 0; x < activeCamera.getWidth(); x++) {
for (int y = 0; y < activeCamera.getHeight(); y++) {
Ray ray = Ray.shootAt(activeCamera.getOrigin(), new Vector(x - activeCamera.getWidth()/2.0, activeCamera.getHeight()/2.0 - y, -(activeCamera.getHeight()/2.0)/Math.tan(activeCamera.getFov() * 0.5)).mul(activeCamera.getDirection()).normalize());
for (Renderable object : scene.getSceneObjects()) {
if (object.intersects(ray)){
//Assign colors to buffered image object "this.image" and do other necessary things
}
}
}
}
}else {
throw new MORISIllegalMethodCallException("The method moris.renderer.MORISRT.setProperties(int, double) should be executed before invoking the method moris.renderer.MORISRT.render(moris.scene.Scene)");
}
}
abstract void onImageRendered(BufferedImage renderedImage);//Here, the BufferedImage object should be "this.image"
The rendered image is something like this:
I tried searching StackOverflow for similar questions and also checked some other sources but they didn't seem to help.
Any suggestions would be appreciated.
Thanks in advance.

abstract void onImageRendered(BufferedImage renderedImage);//Here, the BufferedImage object should be "this.image"
First thing to say is that you are trying to add an implementation detail to an abstract method. That is wrong by definition. If it is an abstract method implementation is delegated to subclasses. But that just means that you are free to use this.image in every subclass. What you can do is, in your abstract class, is having a...
protected BufferedImage image;
...that you can reference from every sublcass as this.image.
But you will have to change the signature of the method render(). It cannot be static if you want to reference this. static methods can only access static attributes, and this always references an instance attribute.
Update
You can call the abstract method in the abstract class:
public abstract class MyAbstractClass {
private BufferedImage image;
public void render() {
// ...
onImageRendered(this.image);
// ...
}
public abstract void onImageRendered(BufferedImage renderedImage);
}
public class MyConcreteClass extends MyAbstractClass {
#Override
public abstract void onImageRendered(BufferedImage renderedImage) {
// do stuff with renderedImage, which will always be the image
// in the rendered metho called on the parent class
}
}

Related

Can you override superclass method in child to do nothing?

I have a parent class and several child classes. I do not want the variable "rotation" to be anything other than 0 for one of the child classes. Is it bad practice to override the methods in that one child class?
public class Parent {
public Parent(double rotation) {
this.rotation = rotation;
}
private double rotation = 0;
public double getRotation() {
return rotation;
}
public void setRotation(double rotation) {
this.rotation = rotation;
}
}
public class RebelChild extends Parent {
public RebelChild () {
super(0);
// TODO Auto-generated constructor stub
}
#Override
public void setRotation(double rotation) {
// do nothing
}
}
If you find yourself in a situation like this, when a method that exists in a superclass is not appropriate for a subclass, then that's a sign that there is something wrong with the design of your class hierarchy.
There should be an "is a" relationship between subclasses and superclasses. This means that an instance of a subclass (such as RebelChild in your example) is an instance of its superclass(es): a RebelChild object is a Parent object. This is the Liskov substitution principle.
If one of the methods of the superclass is not appropriate for the subclass, then you are violating this principle. It means that you cannot treat a RebelChild object like a Parent object.
If the method setRotation is not appropriate for a RebelChild object, then it should not be a subclass of Parent.
When programming, you want to catch errors as early as possible. It is much better to have errors show up when you're compiling than at runtime - that way you'll discover errors much quicker. So, it's better to design your class hierarchy in such a way that the setRotation method is not available at all on RebelChild objects rather than overriding the method to do nothing, or throwing an exception.
Consider a design like this:
public class Thing {
// methods that are appropriate for any kind of Thing
}
public class RotatableThing extends Thing {
public double getRotation() { ... }
public void setRotation(double rotation) { ... }
}
// A specific kind of Thing that can be rotated
public class Something extends RotatableThing {
// ...
}
// RebelChild is a Thing that cannot be rotated
public class RebelChild extends Thing {
}
Alternatively, make Rotatable an interface:
public interface Rotatable {
double getRotation();
void setRotation(double rotation);
}
// Something is a Thing that can also be rotated
public class Something extends Thing implements Rotatable {
// ...
}
// RebelChild cannot be rotated so it does not implement Rotatable
public class RebelChild extends Thing {
// ...
}

How to create an instance that belongs to an interface and implement it

I'm currently learning Java so please bear with my ignorance. Here is my current code
Shape.java
public interface Shape {
public abstract void draw();
}
Rectangle.java
public abstract class Rectangle implements Shape {
private final double width, length;
public Rectangle() {
this(1,1);
}
public Rectangle(double width, double length) {
this.width = width;
this.length = length;
}
public void draw() {
System.out.println("A rectangle of sides " + length + " by " + width + " will be drawn");
}
}
TestPolymorph.java
public class TestPolymorph implements Shape {
public static void main(String[] args) {
Shape[] drawObject = { new Rectangle(40, 60) };
drawObject[0].draw();
}
#Override
public void draw() {
// TODO Auto-generated method stub
}
}
Is there anything wrong with my current code since it's not working. My question is how can I create a drawObject instance that belongs to Shape class and during runtime drawObjectwill be created with two arguments, length and width (giving 40 and 60 for example), draw method of Rectangle will then be invoked.
You're close, there really isn't any need to have your TestPolymorph implement Shape. That is your driver, not a model implementing an interface so you could take that off.
Lastly, remove the abstract from the Rectangle class. That is not an abstract class because you actually want an instance of that type.
Try to remove the abstract modifier from the Rectangle object. You also don't need to implement the Shape interface in TestPolymorph.java
Shape[] drawObject = { new Rectangle(40, 60) };
above is your code
Shape[] drawObject = { new Rectangle(40, 60) {} };
this is correct code
since you are creating objects of abstract class you have to go with this
approach. or you can just remove abstract modifier from Rectangle class
if you are creating a object of abstract class you are forced to implement all its abstract methods , since you dont have any abstract method inside your abstract rectangle class you just have to new Rectangle(40, 60) {}
pass empty brackets at the end bt if your class has abstract methods inside the brackets you have to implement the abstract method
Improving Interface
Every method declaration in the body of an interface is implicitly public and abstract.
Ref: http://docs.oracle.com/javase/specs/jls/se7/html/jls-9.html#jls-9.4
Make it simple. Rather than complicating the things.
Just go in a valid inherited manner.
Remove the abstract from Rectangle class and also there is no need for TestPolymorph to implement the Shape interface.
Rectangle implements the Shape interface and just Test Polymorphism in TestPolymorph.

How to initialize parameter Objects in child class needed for super class constructor?

So, this might sound a bit weird but let me explain. I have a super class that requires multiple parameters. One such parameter is a BufferedImage object. Now obviously, to initialize this BufferedImage in the child class to use as a parameter, I need to use try and catch blocks. The only way I can do that is in a method of the child class called in the constructor. The problem is, the super() constructor must be the first thing in the child class constructor. So I can't call the method to initialize my BufferedImage before calling super(). How can I initialize my BufferedImage object correctly before using it as a parameter when calling super() in my child class constructor?
Example: Super/Parent Class
public class CombatEntity {
BufferedImage sprite;
public CombatEntity(String name, BufferedImage sprite) {
//do something
}
}
Example: Child Class
public class Batman {
BufferedImage sprite;
Batman() {
super("Bruce Wayne", sprite); //sprite hasn't been properly initalized
}
void getSprite() { //I need to call this method before super in order to initalize my image
try {
File f = new File("Batman.png");
sprite = ImageIO.read(f);
}
catch(Exception e) {
//whatever
}
}
}
Do something like this:
At the parent class create normal constructor, which takes name and sprite parameters. Generate getters and setters method following JavaBeans specification.
CombatEntity:
public class CombatEntity {
protected String name;
protected BufferedImage sprite;
public CombatEntity(String name, BufferedImage sprite) {
this.name = name;
this.sprite = sprite;
}
/*
* Getters and Setters
*/
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public BufferedImage getSprite() {
return sprite;
}
public void setSprite(BufferedImage sprite) {
this.sprite = sprite;
}
}
In Batman (child) class create two constructors - one with no parameters, which you can use to create Batman object before you initialize sprite image, and second similiar to parent constructor. When you invoke constructor with no parameters, it invoke parent constructor and set it's parameters to default. Then you can execute generateSpriteImage(String spriteImagePath) to create sprite image from injected path.
Batman:
public class Batman extends CombatEntity{
//Default constructor with no parameters
public Batman(){
super("", null);
}
public Batman(String name, BufferedImage sprite){
super(name, sprite);
}
public void generateSpriteImage(String spriteImagePath) {
try {
File file = new File(spriteImagePath);
this.sprite = ImageIO.read(file);
}
catch(Exception e) {
//whatever
}
}
}
Hope this will help you.
The only way to fix this is to demand an Image parameter in your Batman constructor. This issue is not uncommon, and is one of the reasons to comply with the Javabeans pattern, where every class has a null constructor as well as getters and setters.
Your CombatEntity could define a abstract method getSprite() and call this one in the constructor. The child class (Batman) will have to implement this method.
The advantage is that you don't need to call an extra method after constructing the object (as suggested in the other answer).

How to correctly use the visitor pattern with different Shapes for an Editor

I am creating a editor for different Shape Objects. I stumbled upon the visitor pattern which actually fits my needs I think.
I have a Element class which holds a field named attrs
public class Element {
...
private Shape attrs;
...
}
My Shape class looks like this with the visitor design pattern.
public abstract class Shape {
public abstract void accept(ShapeVisitor v);
public interface ShapeVisitor{
public void visit(CircleObject circle);
public void visit(RectangleObject rectangle);
}
}
And the actual instance of a Shape is defined in a RectangleObject class which extends Shape and holds the Rectangle field. The reasoning for this structure is that I am serializing and deserializing with Jackson for a specifig JSON layout.
public class RectangleObject extends Shape {
private Rectangle rect;
public class Rectangle {
private String fill;
public String getFill() {
return fill;
}
public void setFill(String fill) {
this.fill = fill;
}
#Override
public void accept(JointShapeVisitor v) {
v.visit(this);
}
}
And finally my Editor implements the vistor methods.
public class Editor implements ShapeVisitor{
#Override
public void visit(CircleObject circle) {
}
#Override
public void visit(RectangleObject rectangle) {
}
public void setComponent(JsonArray arguments){
Element element = getFromJson(arguments);
visit(element.getAttrs()); // *** this does obv. not work ***
}
}
The element.getAttrs() returns JointShape, but I need here a CircleObject or a RectangleObject.
How can I pass the correct instance of the ShapeObject to the visit method? Am I doing something completely wrong?
Best regards.
Well ... one little mistake. Because you correctly declared an accept method in your Shape class, you simply must call it:
element.getAttrs().accept(this);
So simply call the accepting method of a shape by providing the editor itself as a visitor. The callback in the shape implementation will call the correct visitor mehod.
What you would do is
public void setComponent(JsonArray arguments){
Element element = getFromJson(arguments);
element.getAttrs().accept(this);
}
And you'll get a callback into one of the visit methods. What you don't get is a return value.
This can be a bit tricky to handle because the callback code is suddenly in no relation to the method that called the accept method. But you often want to pass arguments back and forth between the visiting method and the method that that called accept. To do that, you can add a little to the pattern:
#Override
public Object accept(JointShapeVisitor v, Object context) {
return v.visit(this, context);
}
}
public interface ShapeVisitor{
public Object visit(CircleObject circle, Object context);
..
}
Maybe with a bit of generics to make it typesafe. But even without you can suddenly do
public class Editor implements ShapeVisitor{
#Override
public Foo visit(CircleObject circle, Object context) {
return new Foo(circle, (String) context));
}
#Override
public void visit(RectangleObject rectangle) {
}
public void setComponent(JsonArray arguments){
Element element = getFromJson(arguments);
Foo foo = (Foo)element.getAttrs().visit(this, "Hello");
}
}

Delegating methods to subclasses in Java

I have a superclass Shape, and classes Triangle, Square, etc. extend Shape. I have two current issues:
My method Triangle extends Shape does not compile. It has to return a Shape, not a Triangle.
I want to hide this method. It should only be callable from the Shape superclass.
public class Shape {
public static Shape createShapeFromXML(String xml) {
String type = parse(xml);
if (type.equals("Triangle") {
Triangle.createShapeFromXML(xml);
} else if (...) {
// ...
}
}
}
public class Triangle extends Shape {
public static Triangle createShapeFromXML(String xml) {
....
}
}
public static void main(String[] args) {
String xml = ...
Shape s = Shape.createShapeFromXML(xml);
}
How can I resolve these issues?
why don't you keep the one static method in the superclass, and have it return the appropriate Shape subclass? The signature would stay the same because Triangles have an is-a relationship to Shape.
You could make the method on the superclass private to get the access restriction you want...
Another approach would be to use the Factory pattern. You could have a ShapeFactory...
This is a good idea because creating the xml parsing is not a concern of the Shape classes. Separate your concerns. The wikipedia link is good at describing the pattern, but you might want a simpler example. See this.
// 2. I want to hide this method. It should only be callable from superclass Shape
You can make the Shape method final in order to lock down the implementation. Even your overloaded method that returns a subclass type (Triangle in your example) would be flagged by the compiler.
public static final Shape createShapeFromXML(String xml) { ... }
EDIT:
in response to the conversation in the comments, for evidence I provide the following:
public class Shape {
public static final Shape createShapeFromXML(String xml) {
if (xml.equals("Triangle")) {//removed parse for demo compliation
return Triangle.createShapeFromXML(xml);
} else {
return new Shape();
}
}
}
public class Triangle extends Shape{
public static Triangle createShapeFromXML(String xml) {
return new Triangle();
}
}
trying to compile the above will result in a compiler error:
mybox:src akf$ javac Triangle.java
Triangle.java:3: createShapeFromXML(java.lang.String) in Triangle cannot override createShapeFromXML(java.lang.String) in Shape; overridden method is static final
public static Triangle createShapeFromXML(String xml) {
^
1 error
This can be explained using the JLS by referencing two sections:
from 8.4.6.2 Hiding (by Class Methods):
If a class declares a static method, then the declaration of that method is said to hide any and all methods with the same signature in the superclasses and superinterfaces of the class that would otherwise be accessible to code in the class.
and then from 8.4.3.3 final Methods:
A method can be declared final to prevent subclasses from overriding or hiding it. It is a compile-time error to attempt to override or hide a final method.
Putting the two together, adding final to the signature of a static method will protect that method from being hidden by subclasses. It will enforce compile-time checking.
To make your code compile you need to declare public static Shape createShapeFromXML(String xml) in the Triangle class.
public class Shape {
public static void main(String[] args) {
String xml = "Triangle";
Shape s = Shape.createShapeFromXML(xml);
System.out.println(s.toString());
}
public static Shape createShapeFromXML(String xml) {
Shape aShape = null;
if (xml.equals("Triangle")) {
aShape = Triangle.createShapeFromXML(xml);
}
return aShape;
}
}
class Triangle extends Shape {
public static Shape createShapeFromXML(String xml) {
return new Triangle();
}
#Override
public String toString() {
return "Triangle";
}
}
The System.out.println(s.toString()); in the main method outputs "Triangle", this proves that a Triangle shape is being created.

Categories