how to prevent inheritance chain in java - oop

I have a problem with inheritance chain in java
I have an interface Geometry, a class Circle implements Geometry,and a class Cylinder extends Circle. Because Circle haven't Volume, I return it to 0. When Cylinder extends Circle, Volume return V = PI * Radius * Radius * Height
But I create instance of Cylinder is cy, when it call getVolume(), it return 0 of Circle. How does it call getVolume() itself, not Circle??
Thanks. This is my code:
public interface Geometry {
public double getArea();
public double getVolume();
}
class Circle implements Geometry {
public double R;
public double getArea() {
return Math.pow(R, 2) * Math.PI;
}
public double getVolume() {
return 0; // because not volume of Circle
}
}
class Cylinder extends Circle {
public double Height;
//lateral area of Cylinder
public double getArea() {
double s = super.getArea();
return 2 * s + 2 * Math.PI * super.R * this.Height;
}
public double getVolume() {
return Math.PI * Math.pow(R, 2) * Height;
}
}
public class Main {
public static void main(String[] args) {
Cylinder cy = new Cylinder();
cy.R = 1;
System.out.println(cy.getArea()); // 6.28
System.out.println(cy.getVolume()); // 0 Wrong!!!
}
}

Its not returning the getVolume() of circle, but as you have not set the height the volume is coming as Zero return Math.PI * Math.pow(R, 2) * Height;
You can confirm this by putting a system.out.println statement in the method.
But in any case this hierarchy is incorrect, you should not extend Cylinder with circle as cylinder is not a circle. Inheritance is used to make a specific type from a generic type like dog out of animal, cylinder and circle are not related in that sense , so you are misusing inheritence

I think your problem is not the Circle's getVolume called. The method called is the Cylinder's, but the Height property is 0, hence the 0 return value.
You need to set the Height property of your Cylinder instance (cy), as in:
cy.Height = 3.00;

Inheritance is overused by beginner programmers
Your idea to use inheritance here breaks many many rules in OOP. The most basic of which is that, a cylinder is not a cycle.
There are other mechanisms for code re-usage in OOP, but beginners gravitate towards inheritance because it is obviously FOR re-usage.
Encapsulation and Composition
In this case, I would encourage you to use composition, which is a consequence of encapsulation.
In this case I would encourage you to make a class called Prism that contains two properties, Height and Face, the second of which is where you place your Circle.

Related

how do i get value of data member from subclass?if i have codes like this

I'm still learning flutter/dart language tutorial.
This is my code. I create method that can return an object.How do i get data member from subclass via the method.
abstract class Shape{
get area;
}
class Circle implements Shape{
final radius;
Circle(this.radius);
get area=>pi*pow(radius,2);
}
class Square implements Shape{
final side;
Square(this.side);
get area=>pow(side,2);
}
Shape shapeFactory(String type){
if(type=='circle') return Circle(2);
if(type=='square') return Square(2);
throw 'Can\'t create $type.';
}
void main() {
var s=shapeFactory('square');
print(s.area);
print(s.side);
var c= shapeFactory('circle');
print(c.area);
print(c.radius);
}
as u can see,i can get area value,but i can't get radius or side values from class circle or class square which is subclass of class shape
This is because Shape doesn't have these properties. You need to cast to the specific type first or make shapeFactory generic.
void main() {
var s=shapeFactory('square') as Square;
print(s.area);
print(s.side);
var c= shapeFactory('circle') as Circle;
print(c.area);
print(c.radius);
}
or
T shapeFactory<T extends Shape>(String type){
if(type=='circle') return Circle(2) as T;
if(type=='square') return Square(2) as T;
throw 'Can\'t create $type.';
}
void main() {
var s=shapeFactory<Square>('square');
print(s.area);
print(s.side);
var c= shapeFactory<Circle>('circle');
print(c.area);
print(c.radius);
}

LibGDX stage coordinates change on window resize

I have seen lots of topics on LibGDX and screen/cam coordinates and also some on window resizing, but I just can't find the solution to the following problem I have.
When making a basic stage and a basic actor in this stage, say windowsize 480x320, everything is OK. I can click my actor and it will respond. But when I resize my window, say to 600x320, everything looks right, but my clicklistener is not working anymore. Also, the stage coordinates are moved or messed up.
I use the following code:
stage.addListener(new InputListener() {
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
//determine if actor was hit
System.out.println(stage.hit(x, y, true));
return true;
}
});
Also, I am resizing my stage camera viewport to correspond to the window:
stage.getCamera().viewportWidth = Gdx.graphics.getWidth();
stage.getCamera().viewportHeight = Gdx.graphics.getHeight();
So when resizing, I get the desired effect on screen, but my listener does not respond - the actor seems 'offset' of where I am clicking. What am I doing wrong? Should I move my actor or my cam, or zoom my cam according to the resize? Can someone please explain this to me?
Thanks a lot in advance!
EDIT: below is the complete code of my class.
public class HelpMePlease implements ApplicationListener{
// A standard simple Actor Class
class CustomActor extends Actor {
Texture texture = new Texture(Gdx.files.internal("data/testTex2.png"));
TextureRegion pixelTexture = new TextureRegion(texture, 0, 0, 1, 1);
Sprite sprite = new Sprite(texture);
public CustomActor() {
setWidth(128);
setHeight(128);
setBounds(getX(), getY(), getWidth(), getHeight());
}
#Override
public void draw(SpriteBatch batch, float parentAlpha) {
batch.draw(sprite, getX(), getY(), 0f, 0f, getWidth(), getHeight(), getScaleX(), getScaleY(), getRotation());
}
}
public Stage stage;
public CustomActor actor;
#Override
public void create() {
stage = new Stage(480,320,true);
actor = new CustomActor();
stage.addListener(new InputListener() {
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
//determine if actor was hit
System.out.println(stage.hit(x, y, true));
return true;
}
});
Gdx.input.setInputProcessor(stage);
stage.addActor(actor);
}
#Override
public void resize(int width, int height) {
//resize cam viewport
stage.getCamera().viewportWidth = Gdx.graphics.getWidth();
stage.getCamera().viewportHeight = Gdx.graphics.getHeight();
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
stage.getCamera().update(); //just to be sure, I don't know if this is necessary
stage.act();
stage.draw();
}
#Override
public void pause() {
// TODO Auto-generated method stub
}
#Override
public void resume() {
// TODO Auto-generated method stub
}
#Override
public void dispose() {
// TODO Auto-generated method stub
}
}
You can change your resize por this using the latest nightly.
#Override
public void resize(int width, int height) {
stage.getViewport().update(width, height, true);
}
the last parameter "true" will center the camera in the screen
I think your actor is positioning itself good enough, but your display may be a bit off.
Try
batch.draw(sprite, getX(), getY(), 0f, 0f, getWidth(), getHeight(), getScaleX(), getScaleY(), getRotation());
Instead of
batch.draw(sprite, getX(), getY(), getWidth(), getHeight(), 0f, 0f, getScaleX(), getScaleY(), getRotation());
Spritebatch has the following arguments:
public void draw (Texture texture, float x, float y, float width, float height, int srcX, int srcY, int srcWidth,int srcHeight, boolean flipX, boolean flipY)
I guess you just mixed some arguments up by mistake, would you kindly take a look at it?
Problem solved by updating my LibGDX Version using Gradle and using the new Viewport options!
Thanks for taking the time everyone!
In my case adding
stage.getViewport().setScreenSize(width, height);
in resize() solved problem

Stage, viewport, camera, scaling, and Nexus 7

I am a newbies in Android and I am learning how to use libgdx as well. I found a few tutorials that use the “DisplayScreen extends AbstractScreen” coding technique, and they use Stage and Actor for displaying output. My interpretation of this coding technique is that DisplayScreen will use whatever in AbstractScreen unless it is #Override (please correct me if I am wrong).
Therefore, if I place the code in AbstractScreen resize() to scale the display to a bigger screen yet maintaining the aspect ratio; the stage in DisplayScreen should resize it to fit the bigger screen. The main objective is that I only want to concentrate my game development in 800x480 environment and completely ignore all different sizes/resolution. The resize() in AbstractScreen will do all the hard work to scale and fit my game to any resolution.
Please allow me to use my test example for better explanation. I have no problem displaying my 800x480 black background on my phone. However, the same background was displayed BUT not maintaining its aspect ratio on Nexus 7.
This turorial fixed my problem mentioned above (I adopted to have two black bars on both side of the screen). However, I have a small problem integrating this solution to the “DisplayScreen extends AbstractScreen” technique.
Please see this screen shot here. My issues are:
Why my black box is not resize to fit the screen, yet leaving two red bar on both sides of the screen?
I don’t understand why the black image only displaying 766x480 on my Nexus 7?
It will be fantastic if someone can point me to the right direction.
Code for awesomegame
package com.example.somegame;
import com.badlogic.gdx.Game;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.assets.AssetManager;
import com.example.somegame.screens.DisplayScreen;
public class awesomegame extends Game {
public static AssetManager AssetManager = new AssetManager();
#Override
public void create() {
}
#Override
public void render() {
super.render();
}
#Override
public void resize(int width, int height) {
super.resize(width, height);
setScreen( new DisplayScreen(this) );
}
#Override
public void setScreen(Screen screen) {
super.setScreen( screen );
}
Code for AbstractScreen
package com.example.somegame.screens;
import com.example.somegame.awesomegame;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.Scaling;
public class AbstractScreen implements Screen{
private awesomegame awesomegame;
private Stage stage;
private BitmapFont font;
private SpriteBatch batch;
private OrthographicCamera camera;
public AbstractScreen(awesomegame awesomegame) {
this.awesomegame = awesomegame;
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
camera.update();
stage = new Stage(800, 480, false);
}
#Override
public void render(float delta) {
stage.act( delta );
Gdx.gl.glClearColor( .5f, .5f, 0f, 1f );
Gdx.gl.glClear( GL20.GL_COLOR_BUFFER_BIT );
stage.draw();
}
#Override
public void resize(int width, int height) {
Vector2 size = Scaling.fit.apply(800, 480, width, height);
int viewportX = (int)(width - size.x) / 2;
int viewportY = (int)(height - size.y) / 2;
int viewportWidth = (int)size.x;
int viewportHeight = (int)size.y;
Gdx.gl.glViewport(viewportX, viewportY, viewportWidth, viewportHeight);
stage.setViewport(800, 480, true);
}
Code for DisplayScreen
package com.example.somegame.screens;
import com.example.somegame.awesomegame;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
public class DisplayScreen extends AbstractScreen {
private Image loadingBg;
private Stage stage;
float loadingPercent;
public DisplayScreen(awesomegame awesomegame) {
super (awesomegame);
}
#Override
public void show()
{
super.show();
awesomegame.AssetManager.load("img/loading.atlas", TextureAtlas.class);
awesomegame.AssetManager.finishLoading();
stage = new Stage();
TextureAtlas atlas = awesomegame.AssetManager.get("img/loading.atlas", TextureAtlas.class);
loadingBg = new Image(atlas.findRegion("loadingBg"));
loadingBg.setSize(800, 480);
loadingBg.setX(0);
loadingBg.setY(0);
stage.addActor(loadingBg);
// add all asset need to be loaded here. for example
// awesomegame.AssetManager.load("img/whatever.pack", TextureAtlas.class);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor( 1f, 0f, 0f, 1f );
stage.draw();
}
The Nexus 7 has a screen resolution of 1280 x 800, but part of the height is used for the onscreen menu panel (with the back/home/menu buttons).
The main culprit in your code is here, where you try to enforce a specific aspect ratio that doesn't fit this adjusted dimension, resulting in those bars on the side:
public void resize(int width, int height) {
Vector2 size = Scaling.fit.apply(800, 480, width, height);
...
}
Looks like you pulled that resize function off another stackoverflow post. I had done the same, but switched to something simpler when i ran into the same issue:
public void resize(int width, int height) {
stage.setViewport(true, width,height);
stage.getCamera().setToOrtho(false,width,height);
...
}
This code works for me with the latest update:
OrthographicCamera is cam, this makes no cropping, just changes the viewport so the width is still "that many" times larger than the actual window/device
public void resize(int width, int height) {
int newW = width, newH = height;
if (cam.viewportWidth > width) {
float scale = (float) cam.viewportWidth / (float) width;
newW *= scale;
newH *= scale;
}
// true here to flip the Y-axis
cam.setToOrtho(true, newW, newH);
}

unresolved token - c++

I am trying to solve a lesson in my study. I am going to have an abstract class, CFigure, on top and different figures below, currently I have made a circle class. I am going to call this from a C# program.
But when I try to build my code I get the following error messages:
unresolved token (06000001) arealBeregnerCPP.CFigure::area
unresolved token (06000002) arealBeregnerCPP.CFigure::circumference
2 unresolved externals
I hope anyone can give me a hint in what I do wrong... Thanks!
This is my program:
// arealBeregnerCPP.h
#pragma once
using namespace System;
namespace arealBeregnerCPP {
public ref class CFigure
{
public:
virtual double area();
virtual double circumference();
};
public ref class CCircle : public CFigure
{
private:
double m_radius;
public:
CCircle(double radius)
{
m_radius = radius;
}
virtual double area() override
{
return 0; //not implementet
}
virtual double circumference() override
{
return 0; //not implementet
}
};
}
if CFigure::area() and CFigure::circumference() are abstract functions then put = 0 in declaration:
virtual double area() = 0;
virtual double circumference() = 0;
Probably you haven't defined area and circumference.
Since you fail to present complete code there are some other possibilities, such as failing to link with the relevant files.
By the way, please don't tag c++/cli questions as c++. Microsoft's c++/cli is not c++. It's a language similar to c++, but it's not c++.
Cheers & hth.,

What is needed in this call to gdk_get_pixmap?

I have created a little drawing area class and now need a pixmap to draw into during the expose event callback. But I can't get any parameter that I have tried to compile. Here are the relevant parts of the code...
The class definition...
class set_display_drawing_area : public Gtk::DrawingArea
{
public:
set_display_drawing_area ();
virtual ~set_display_drawing_area ();
protected:
virtual bool on_expose_event(GdkEventExpose* event);
private:
GdkPixmap *pixmap_ptr;
};
and the expose callback...
bool set_display_drawing_area::on_expose_event(GdkEventExpose* event)
{
Glib::RefPtr<Gdk::Window> window = get_window();
if (window)
{
Gtk::Allocation allocation = get_allocation();
const int width = allocation.get_width();
const int height = allocation.get_height();
pixmap_ptr = gdk_pixmap_new (window, // <-- What is needed here?
width,
height,
-1);
You're mixing gtkmm (C++) and gtk (C) style code here. gdk_pixmap_new is a C function which has no idea about templates and classes (such as Glib::RefPtr). You'll probably want to use gtkmm for your pixmap as well:
Glib::RefPtr<Gdk::Pixmap> pixmap;
and
pixmap = Gdk::Pixmap::create(window, width, height);