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
Related
I've got the problem. I want to have 2 classes that extend from 1 abstract class. The problem is these 2 subclasses have different variables, so when I want to create a vector of an abstract class that will contain both subclasses I can't access these variables. Here is an explanation of what I want to do exactly:
abstract class Plane {
protected float x, y;
}
class MilitaryPlane extends Plane {
private String ammoType;
}
class PassengerPlane extends Plane {
private int passengersAmount;
}
public static void main() {
Plane newPlane = new MilitaryPlane;
newPlane.ammoType = "bomb"; //error: cannot resolve symbol ammoType
}
Is there any better thing than casting newPlane object into Plane 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);
}
}
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.
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.
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.