Constructing a Subclass Object in a Completely Different Class - java

So lets say i have the following code.
public class ImageMaker {
// Variables
static ArrayList<Shape> shapes = new ArrayList<Shape>();//all the shapes contained in the image
public static void main (String[] args) {
shapes.add(new Rect()); //here i want to add an object Rect
}
}
and in a different class called Shape shown below. Now I want to add an object of type Rect to my shapes array list but i cannot as it says Rect cannot be resolved to a type. How can i implement this? Of course i have more instance variables and methods but i did not show them. Let me know if you need more info to answer. Thanks!
public class Shape {
public class Rect extends Shape {
//rect instance variables
public Rect(){
super();
System.out.print("Youve made a rect within shape");
}
}

As #tsnorri mentioned in comment, you should simply declare Rectas class out of Shapeone.
public class Shape {
}
public class Rect extends Shape {
//rect instance variables
public Rect(){
super();
System.out.print("Youve made a rect within shape");
}
}
In case you want to learn more about nested classes in Java this is a good starting point: http://docs.oracle.com/javase/tutorial/java/javaOO/nested.html
Edit (working example)
In general I recommend you some reading about basics of OO programming and JAVA in general.
here's a working example of adding both Shape and Rect to an ArrayList.
import java.util.ArrayList;
class ImageMaker
{
static ArrayList<Shape> shapes = new ArrayList<Shape>();//all the shapes contained in the image
public static void main(String args[])
{
shapes.add(new Shape());
shapes.add(new Rect());
}
public static class Shape {
System.out.print("Created new Shape");
}
public static class Rect extends Shape {
//rect instance variables
public Rect(){
super();
System.out.print("You've made a rect within shape");
}
}
}
cheers

Make the class static:
public static class Rect extends Shape {
Then use new Shape.Rect()
However, that seems like poor use of nested classes and you should consider defining Rect outside Shape in it's own file.

Related

Java use of is-A and has-A relationships

How come I can't use the variable shapeArea in my circle class? I'm trying to build a series classes with is-a relationships and has-a relationship for the first time. The empty classes don't really have a purpose yet. I was just trying to see if I could create the basic frame for what would eventually hold my code.
public class Object {
}
class shape extends Object{
}
class area{
public double area;
}
class TwoDshape extends shape{
area shapeArea = new area();
}
class circle extends TwoDshape{
shapeArea.area = 1;
}
You can use it in any method in circle class or in any type of constructors of circle class because the inherited fields only can be accessed through constructors and methods in the child class.
I created a Replit snippet.
class Main {
public static void main(String[] args) {
Shape2D shape = new Shape2D();
System.out.println(shape.area.sqm);
// Casting objects
// https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
Shape2D circle = new Circle();
System.out.println(circle.area.sqm);
Shape2D triangle = new Triangle(2.0);
System.out.println(triangle.area.sqm);
Rectangle rectangle = new Rectangle();
rectangle.increaseArea();
System.out.println(rectangle.area.sqm);
}
}
/*
Extends java.lang.Object
But if you omit that, it will extend implicitly.
https://docs.oracle.com/javase/tutorial/java/IandI/objectclass.html
https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
*/
class Shape extends Object {
}
class Area {
public double sqm;
}
class Shape2D extends Shape {
Area area = new Area();
}
/*
Initializing Instance Members
https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
*/
class Circle extends Shape2D {
{
area.sqm = 1.0;
}
}
/*
Using a constructor
https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
*/
class Triangle extends Shape2D {
Triangle(double areaInSquareMetres) {
this.area.sqm = areaInSquareMetres;
}
}
/*
Using an instance method
https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
*/
class Rectangle extends Shape2D {
void increaseArea() {
area.sqm += 1.0;
}
}
Also important:
Whats the difference between objects and data structures?
At the class level you can only define variables (static or instance), constructor, methods. You can do something like
class Circle extends TwoDshape{
public Circle {
shapeArea.area = 1;
}
}
Plus: Prefer starting class names with capital letter

The public type Main must be defined in its own file [duplicate]

This question already has answers here:
Why are filenames in Java the same as the public class name? [closed]
(7 answers)
Closed 4 years ago.
public interface Shape { }
class Circle implements Shape {
Circle(int radius) { /* ... */ }
}
class Rectangle implements Shape {
Rectangle(int height, int width) { /* ... */ }
}
public class Main {
public static void main (String[] args) {
Shape[] shapes = new Shape[2];
shapes[0] = new Circle(1);
shapes[1] = new Rectangle(1, 2);
writeShapes(shapes);
}
public static void writeShapes(Shape[] shapes){
for(Shape shape:shapes){
if(shape instanceof Circle) System.out.println("Circle");
else if(shape instanceof Rectangle) System.out.println("Rectangle");
}
}
In the example, I want to add new shape. However, I could not get the point what's going on about the error
"The public type Main must be defined in its own file"
which occurs on my main method. I have tried to add "static" in front of main, but it does not work! Any suggestions are appreciated!
A .java file can contain only one public class/interface.
In your case, you can either move the Main class or Shape interface to another file.
A .java file can only have one public class/ interface. So you might want to move one of the classes out of the file. You can still, however, call it in the main class using object variables.
Since you are not using any actionListeners, then inner classes don't make sense and are not useful.

why cant we use a reference variable of super class to access methods of its subclass(methods not available in super class)?

I know that,No matter what the actual object is,that the reference variable refers to,The methods i can call on a reference is dependent on the declared type of the variable (in line 15 of code).I want to know why so.Why can't the class user use the reference variable s of type Shape to call its subclass method drawCircle()?
public class Shape{
public void displayShape(){
System.out.println("shape displayed");
}
public class Circle extends Shape{
public void drawCircle(){
System.out.println("circle drawn");
}
public class Test{
p.s.v.main(String[] a){
Circle c=new Circle();
Shape s=new Shape();
display(c);
display(s);
public void display(Shape myShape){
myShape.displayShape();//possible for ref variable c and s
myShape.drawCircle();//not possible for reference var s
}
}
}
Can u provide me an explanation of what happens at the object level?I am new to java.
The compiler just knows that myShape is a reference variable of type Shape, which contains only one method displayShape() , so according to the compiler, it is not possible to call a method drawCircle() which the Shape class does not contain.
The compiler is not concerned with what object this variable will hold at runtime. You may extend another class from the Shape class at some later point of time, and use the myShape reference to hold that subclass object. The compiler is just concerned with what type myShape is at compile-time.
If your Circle class happened to override the displayShape() method, like below :
public class Circle extends Shape {
public void displayShape() {
System.out.println("I am a Circle!");
}
public void drawCircle() {
// Implementation here
}
}
the only decision happening at runtime would be which displayShape() method to call.
First, you forgot to make Circle subclass of Shape.
Then you said :
The methods i can call on a reference is dependent on the declared
type of the variable
But the Shape myShape parameter is also a variable :
public void display(Shape myShape){
...
myShape.drawCircle();
}
So also here, as for a local variable or a field variable, the compiler relies only the declared type to bound the invoked method.
And as the Shape class is used as the type of the declared variable, only methods of this class may be invoked on.
If you are sure that myShape is a Circle you can explicitly cast it to one
((Circle)myShape).drawCircle(); or Circle myCircle = (Circle)myShape; myCircle.drawCircle(); but if you do that and it isn't actually a Circle then you will get a ClassCastException.
Generally, you want to try and avoid this sort of casting though as its something of a code smell which suggests your design is a bit off. (Sometimes you do need to do it, but its not taking advantage of polymorphism).
To take advantage of polymorphism you would instead have Shape define displayShape() as an abstract method and then instead of drawCircle(), drawSquare() etc... each subclass of Shape will have its own version of the displayShape() method, while in Shape itself you would have:
public abstract displayShape(); which is a way of telling the compiler "all my subclasses will have this displayShape() method so when someone calls displayShape() on one of me, use the one defined in that subclass".
So for example:
Shape myCircle = new Circle();
Shape mySquare = new Square();
myCircle.displayShape(); //draws a circle
mySquare.displayShape(); //draws a square
//And if you can't choose which one you want...
Shape surpriseMe = new Random().nextBoolean() ? myCircle : mySquare;
surpriseMe.displayShape(); //draws either a circle or a square!
How about reading about polymorphism.
public abstract class Shape {
public abstract void draw();
}
public class Circle extends Shape {
#Override
public void draw() {
System.out.println("Circle drawed");
}
}
public class Triangle extends Shape {
#Override
public void draw() {
System.out.println("Triangle drawed");
}
}
public class Test() {
public static void display(Shape shape) {
shape.draw();
}
public static void main(String[] args) {
//how can you define "shape" in real world? its triangle or... -> abstraction
Circle c = new Circle();
Triangle t = new Triangle();
display(c);
display(t);
}
}

Making different screens using Processing in Eclipse

I have been having some issue's with using proclipsing (or processing in eclipse). I want to make it starts in one class, and draws everything in the other. Here is my code:
CLASS "Class1":
import processing.core.PApplet;
public class Class1 extends PApplet {
public void setup() {
size(600,600);
}
public void draw() {
background(0);
Class2 ChangeClass = new Class2();
ChangeClass.draw();
}
}
CLASS "Class2":
import processing.core.PApplet;
public class Class2 extends PApplet{
public void draw() {
background(100);
}
}
And when I attempt to run the program from Class1, this appears in the console:
Exception in thread "Animation Thread" java.lang.NullPointerException
at processing.core.PApplet.background(PApplet.java:15122)
at Class2.draw(Class2.java:6)
at Class1.draw(Class1.java:11)
at processing.core.PApplet.handleDraw(PApplet.java:2386)
at processing.core.PGraphicsJava2D.requestDraw(PGraphicsJava2D.java:240)
at processing.core.PApplet.run(PApplet.java:2256)
at java.lang.Thread.run(Unknown Source)
Can you tell me why this appears and why it doesn't work?
If you're using eclipse, then you must have a main() method that looks something like this:
public static void main(String args[]){
PApplet.main(new String[] {"Class1"});
}
In order to use another PApplet, you have to also call its main function:
public static void main(String args[]){
PApplet.main(new String[] {"Class1"});
PApplet.main(new String[] {"Class2"});
}
The whole thing would look something like this:
Class1.java
import processing.core.PApplet;
public class Class1 extends PApplet {
public void setup(){
size(600, 600);
}
public void draw(){
background(0);
}
public static void main(String args[]){
PApplet.main(new String[] {"Class1"});
PApplet.main(new String[] {"Class2"});
}
}
Class2.java
import processing.core.PApplet;
public class Class2 extends PApplet {
public void draw(){
background(100);
}
}
You could even move the main() function into its own file.
Roughly speaking, you should only have 1 PApplet. It grabs control of the drawing context (like a canvas) and owns it. In the draw method, it draws everything you want on that canvas and unless you explicitly pass the canvas somewhere else, it won't be able to draw on it. The error is happening because the second PApplet class is requesting to draw on the canvas and the original PApplet doesn't expect or allow that.
I would suggest that you don't instantiate the class Class2 in every draw method, that's 60 times a second (or whatever) you'll be creating a new object. Instead, consider this approach:
import processing.core.PApplet;
public class Class1 extends PApplet {
Class2 changeClass;
public void setup() {
size(600,600);
changeClass = new Class2();
}
public void draw() {
background(0);
changeClass.draw();
}
}
Now, this is not enough because the changeClass draw method will not receive enough info to draw by itself. It will need that canvas.
The proper way to do what you want is probably to use 'handleDraw' or 'registerMethod' from the documentation. It seems like these are designed to let you specify another object to handle the drawing (or a library to do so).
Finally, it's probably not kosher, but you could grab the drawing context as a PGraphics object and pass it to your draw method and draw everything directly to that, but using the provided methods above is probably cleaner.
Edit: Adding a quick code example as requested.
I'm afraid I don't have Eclipse or Proclipsing any more, but hopefully this Processing example is easily ported:
void setup()
{
size(800, 600, OPENGL);
// Register the Drawer Object as the method to call "draw" on after the PApplet draw is called
registerMethod("draw", new Drawer());
// States set here will apply to both draw methods
rectMode(CENTER);
}
void draw()
{
// This happens first...
background(255, 255, 255);
// More drawing if need be...
}
public class Drawer
{
void draw()
{
// This happens second (every draw)
translate(width/2, height/2);
rect(0, 0, frameCount, frameCount);
// more drawing if need be...
}
}
Just adding to the already great answers: another option could be passing a reference to the sketches' graphics so a second class can draw into:
import processing.core.PApplet;
import processing.core.PGraphics;
public class Class1 extends PApplet {
Class2 changeClass = new Class2();
public void setup() {
size(600,600);
}
public void draw() {
background(0);
changeClass.draw(g);
}
public static void main(String[] args) {
PApplet.main(Class1.class.getCanonicalName());
}
}
class Class2{
public void draw(PGraphics g) {
g.background(100);
}
}

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