Efficient way to keep referencing a class in multiple linked java classes? - java

suppose in Eclipse I have three packages with the following classes in each:
Packages: Classes
Head: head.java
Body: arms.java
Legs: feet.java
I want to define class info in brain.java and pass it through methods to the other classes (arms.java and feet.java) and update the contents of info.
class info {
// some vars such as bools,ints,strings
}
For example, have updateArms be a method defined in arms.java. I want to do the following in brain.java:
arms.updateArms( info );
I am having trouble finding how to first define a class that behaves this way, and secondly how to pass it as a parameter to another linked class.

First, you should learn about Java naming convention.
For example, package should be head, and the class should be Head.
Go back to your design: In OOP, we see the program as interactions between object instances.
In your example, it may look like:
class Arm {
void moveUp(SomeInfo info) {
...
}
}
class Brain {
private Arm leftArm;
private Arm rightArm;
void reachForward() {
rightArm.moveUp(...);
}
void connectLeftArm(Arm arm) {
this.leftArm = arm;
}
//....
}
class Body {
Brain brain;
Arm leftArm;
Arm rightArm;
public Body() {
this.brain = new Brain();
this.leftArm = new Arm();
this.rightArm = new Arm();
this.brain.connectLeftArm(this.leftArm);
this.brain.connectRightArm(this.rightArm);
}
}
I wish this demonstrate the difference of way of thinking.
If you start get used to the way OOP see things, then you can take next step in refining your design (e.g. by different design pattern)

You can achieve this using Inheritance.
Inheritance can be defined as the process where one class acquires the properties (methods and fields) of another. With the use of inheritance the information is made manageable in a hierarchical order. The class which inherits the properties of other is known as subclass (derived class, child class) and the class whose properties are inherited is known as superclass (base class, parent class).
Sample Code helps you how to use the methods and properties of other classes.
class Calculation {
int z;
public void addition(int x, int y) {
z = x + y;
System.out.println("The sum of the given numbers:"+z);
}
public void Subtraction(int x, int y) {
z = x - y;
System.out.println("The difference between the given numbers:"+z);
}
}
public class My_Calculation extends Calculation {
public void multiplication(int x, int y) {
z = x * y;
System.out.println("The product of the given numbers:"+z);
}
public static void main(String args[]) {
int a = 20, b = 10;
My_Calculation demo = new My_Calculation();
demo.addition(a, b);
demo.Subtraction(a, b);
demo.multiplication(a, b);
}
}

Related

A variable that could take different types in?

TLDR: I need a variable that can take in an object from either of 2 classes.
I'm working on a Java 2D game, still getting the basics to work and here I have a problem: in the class Actor, in the constructor, the actor generates its hitbox (4 XY coordinates object) and then adds that hitbox to a list of things that need to check for collisions.
But now that I got all this working, I made a new class, Platform, so that my character can walk on something else than the defiled corpses of it's enemies. But in the Rect constructor, I have a variable (Parent) that sets itself to the object that called the constructor (with itself in parameter) so I would get hitbox.parent() = player for example.
But since the Platform objects are from another class (that I don't really want to inherit from the Actor class) how can I make it so that Rect and give itself a parent of different type ?
Edit
The class as it is now
package misc;
import item.Platform;
import npc.Actor;
public class Rect {
int x,y,wdt,hgt;
public Rect(Actor a){
x = a.x;
y = a.y;
wdt = a.wdt;
hgt = a.hgt;
}
public Rect(Platform p){
parent = p;
x =p.x;
y =p.y;
wdt =p.wdt;
hgt =p.hgt;
}
}
And here is the place where I have trouble calling it
private static void collision(Rect r1,Rect r2){
if (r1.y -r2.y <= r2.hgt && r1.y -r2.y >= -r2.hgt){
r1.parent.yCol = true;
}else{
r1.parent.yCol = false;
}
if (r1.x -r2.x <= r2.wdt && r1.x -r2.x >= -r2.wdt){
r1.parent.xCol = true;
}else{
r1.parent.xCol = false;
}
}
In addition to inheritance, you could also use an interface based approach.
public interface GameRect {
int getX();
int getY();
int getHeight();
int getWidth();
}
public class Actor implements GameRect {
// implementation
}
public class Platform implements GameRect {
// implementation
}
public class Rect {
// implementation
private GameRect parent;
// constructor works for all classes that implement GameRect interface
public Rect(GameRect gr) {
parent = gr;
x = gr.getX();
y = gr.getY();
// etc
}
}
The problem with a solution like this is that you need to cast back to the original type (Actor, and Platform respectively) every time you want to call class methods on the parent objects that are not GameRect interface methods.
You need to use Inheritance, which is one of the most important aspects of Object Oriented Programming. You need to do some reading on it so you understand how it works and how to use it: https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

How would I access an int variable from one class to another? (Java)

For example:
In Class One
int killcount = 0;
In Class Two
killcount = 5;
All I want to do I get the variable from one class to another class. How would I do that?
Before trying to work with Bukkit I'd recommend you to get some Java experience first. That's not meant as an insult, but it can get quite confusing if you do it the other way round. Anyways, if you still want to know the answer to your question:
You'll have to create a getter & setter for your "killcount" variable.
class Xyz {
private int killcount;
public void setKillcount(int killcount) {
this.killcount = killcount;
}
public int getKillcount() {
return this.killcount;
}
}
Of course this is a simplified version without checks, but if you want to access the variable from a different class you can create an instance and use the methods to modify it.
public void someMethod() {
Xyz instance = new Xyz();
instance.setKillcount(instance.getKillcount() + 1);
//this would increase the current killcount by one.
}
Keep in mind that you'll have to use the same instance of the class if you want to keep your values, as creating a new one will reset them to default. Therefore, you might want to define it as a private variable too.
Consider the examples
public class Test {
public int x = 0;
}
This variable x can be accessed in another class like
public class Test2 {
public void method() {
int y = new Test().x;
// Test.x (if the variable is declared static)
}
}
Ideally, the instance variables are made private and getter methods are exposed to access them
public class Test {
private int x = "test";
public int getX() {
return x;
}
public void setX(int y) {
x = y;
}
}

One class included to other class by composition. How to change it's private fields?

I have simple class:
public class Points {
private int x = 0;
public void setX(int x) {
this.x = x;
}
}
And I make other class which have a Points field:
public class Curve {
private Points p;
public void setX(int x) {
p.setX(x);
}
}
So, setX(int x) method in class Curve is used to change value of private field x in Points.
Finally I use this method in such way:
public class UseComposition {
public static void main(String[] args) {
// TODO Auto-generated method stub
Curve c = new Curve();
c.setX(1);
}
}
I think, this code have a doubling: if I change a method name in Points I also have to change method setX in class Curve.
Are there other ways to solve such task?
May be it isn't a good idea at all to change such private values. Please, help.
I think, this code have a doubling: if I change a method name in Points I also have to change method setX in class Curve.
No you don't. You can if you want, but the two methods are independent. You don't have to expose all the methods within Points at all, and indeed most of the time you wouldn't want to. You should only expose methods which are relevant to the class you're writing. Sometimes they may just delegate down via a single field, but often they'll involve multiple fields, or you'll need to do other things as well as calling the delegated method.
Your code is correct. Just think carefully on the names before continue the work, and you wont have trouble...
Or, you might consider creating an interface, that implement basic features that are shared with others. In that way, if you add/change/remove things on the interface, classes that have that interface implemented will not compile, and show that clearly to you, like:
Missing Interface method: "setNewX"...
There is another way to do it. You can provide access to p via a public getter like below:
public class Curve {
private Points p;
public void setX(int x) {
p.setX(x);
}
public Points getPoints(){
return p;
}
}
After this, you can change the Points class all you want without having to change the method names for both Points and Curve. You would just have to access p like below.
public class UseComposition {
public static void main(String[] args) {
// TODO Auto-generated method stub
Curve c = new Curve();
Points p = c.getPoints();
p.setX(1);
}
}
Use getter in Curve class
public Points getPoints() {
return p;
}
then in main method access X property like this:
Curve c = new Curve();
Points p = c.getPoints();
p.setX(1);
You can use property as Point class
public class Point {
private int x = 0;
public void setX(int x) {
this.x = x;
}
}
public class Curve {
Point cenetrPoint;
public void setCenterPoint(Point p) {
this.cenetrPoint = p;
}
}

use variable with "new" when creating object

I am designing a virtual aquarium. I have a class: Fish which I inherit to create classes of different species. The user can select the species in a combo box and click a button to put the fish in the tank. I use the following code to create the fish:
switch(s){
case "Keegan" :
stock.add(new Keegan(this, x,y));
break;
case "GoldenBarb" :
stock.add(new GoldenBarb(this, x,y));
"stock" is a LinkedList and "s" is the String selected in the Jcombobox. As it stands I will have to create a long switch when I add a bunch of different species. I would like the code to look like:
stock.add(new s(this,x,y));
and dispense with the switch such that all I have to do is create the class and add its name to the combo box and have it work. Is there a way to do so? Any help is appreciated.
You want to use a bunch of factory objects, stored in a Map under the string keys that you use in the switch.
These are the classes for the various fish you should already have.
abstract class FishBase {}
class Keegan extends FishBase {
Keegan(Object _this, int x, int y) {
// ...
}
}
class GoldenBarb extends FishBase {
GoldenBarb(Object _this, int x, int y) {
// ...
}
}
An interface for all the fish factories. A fish factory represents a way to create some type of fish. You didn't mention what the constructor signature is so I just picked some types.
interface IFishFactory {
FishBase newFish(Object _this, int x, int y);
}
Set up one factory for every fish type. These obviously don't need to be anonymous classes, I'm using them to cut down on clutter.
Map<String, IFishFactory> fishFactories = new HashMap<>();
fishFactories.put("Keegan", new IFishFactory() {
public FishBase newFish(Object _this, int x, int y) {
return new Keegan(_this, x, y);
}
});
fishFactories.put("GoldenBarb", new IFishFactory() {
public FishBase newFish(Object _this, int x, int y) {
return new GoldenBarb(_this, x, y);
}
});
Then just pick the factory from the Map using the string you already have. You might want to check whether a factory for the given name exists.
stock.add(fishFactories.get(s).newFish(this, x, y));
Now, if all your fish classes have the exact same constructor signature, you can create a single factory class that can handle all of them using reflection, and get rid of some boilerplate.
class ReflectionFishFactory implements IFishFactory {
Constructor<? extends FishBase> fishCtor;
public ReflectionFishFactory(Class<? extends FishBase> fishClass)
throws NoSuchMethodException {
// Find the constructor with the parameters (Object, int, int)
fishCtor = fishClass.getConstructor(Object.class,
Integer.TYPE,
Integer.TYPE);
}
#Override
public FishBase newFish(Object _this, int x, int y) {
try {
return fishCtor.newInstance(_this, x, y);
} catch (InstantiationException
| InvocationTargetException
| IllegalAccessException e) {
// this is terrible error handling
throw new RuntimeException(e);
}
}
}
Then register it for every applicable subclass.
for (Class<? extends FishBase> fishClass :
Arrays.asList(Keegan.class,GoldenBarb.class)) {
fishFactories.put(fishClass.getSimpleName(),
new ReflectionFishFactory(fishClass));
}
I think reflection might be what you are looking for. This allows you to avoid the switch statement, which is what you are asking.
Reflection (among other things) allows you to run methods with just strings. So in Java, where you would normally call a method like this:
new Foo().hello();
With Reflection, you can use a string to call the method, like this:
Class<?> clazz = Class.forName("Foo");
clazz.getMethod("hello").invoke(clazz.newInstance());
Java Constructor Reflection example.
Regarding the Factory pattern (referring now to other answers), as I understand it, that is just encapsulating the switch statement (or whatever method you choose to use). The Factory pattern itself is not a means of avoiding the switch statement. The Factory Pattern is a good thing, but not what you were asking. (You will probably want to use the factory pattern in any case).
Let's go step by step to see how far you want to go.
First, you can abstract out the creation of fish in a FishFactory, so that the original place you do the switch statement can simply changed to
stock.add(fishFactory.createFish(s, x, y));
Then the switch case goes to the factory:
public class SimpleFishFactory {
#Override
public Fish createFish(String fishType, int x, int y) {
switch(s){
case "Keegan" :
return new Keegan(this, x,y);
break;
case "GoldenBarb" :
return new GoldenBarb(this, x,y);
//....
}
}
}
(I assume all your fish is having same interface/base class as Fish)
If you want to make the creation look more elegant, there are two common ways to choose from:
Reflection
Idea is simple. First setup a lookup table of string vs fish class (or constructor), and each createFish() is creating new instance of fish by reflection
public class ReflectionFishFactory {
private Map<String, Class<? extends Fish>> fishClasses = new HashMap<...>();
public ReflectionFishFactory() {
//set up fishClasses with name vs corresponding classes.
// you may read it from file, or hard coded or whatever
fishClasses.put("Keegan", Keegan.class);
fishClasses.put("GoldenBarb", GoldenBarb.class);
}
#Override
public Fish createFish(String fishType, int x, int y) {
Class<?> fishClass = fishClasses.get(fishType);
// use reflection to create new instance of fish by
// by using fishClass
}
}
Prototype Pattern
For some reason, you may not want to use reflection (maybe due to slowness of reflection, or different fishes have very different way to create), you may look into Prototype Pattern of GoF.
public class PrototypeFishFactory {
private Map<String, Fish> fishes = new HashMap<...>();
public ReflectionFishFactory() {
//set up fishClasses with name vs corresponding classes.
// you may read it from file, or hard coded or whatever
fishClasses.put("Keegan", new Keegan(....) );
fishClasses.put("GoldenBarb", new GoldenBarb(....) );
}
#Override
public Fish createFish(String fishType, int x, int y) {
return fishes.get(fishType).cloneNewInstance(x, y);
}
}
A combination of enums and factory strategies could be used for a simple, type-safe, way of creating object instances from Strings and for providing a set (or array) of Strings.
Take the follwoing eample -
import java.util.HashMap;
import java.util.Map;
public enum FishType {
BLUE_FISH(BlueFish.class, new FactoryStrategy<BlueFish>(){
public BlueFish createFish(int x, int y) {
return new BlueFish(x, y);
}}),
RED_FISH(RedFish.class, new FactoryStrategy<RedFish>(){
public RedFish createFish(int x, int y) {
//an example of the increased flexibility of the factory pattern - different types can have different constructors, etc.
RedFish fish = new RedFish();
fish.setX(x);
fish.setY(y);
fish.init();
return fish;
}});
private static final Map<Class<? extends Fish>, FactoryStrategy> FACTORY_STRATEGY_MAP = new HashMap<Class<? extends Fish>, FactoryStrategy>();
private static final String[] NAMES;
private FactoryStrategy factoryStrategy;
private Class<? extends Fish> fishClass;
static {
FishType[] types = FishType.values();
int numberOfTypes = types.length;
NAMES = new String[numberOfTypes];
for (int i = 0; i < numberOfTypes; i++) {
FishType type = types[i];
FACTORY_STRATEGY_MAP.put(type.fishClass, type.factoryStrategy);
NAMES[i] = type.name();
}
}
<F extends Fish> FishType(Class<F> fishClass, FactoryStrategy<F> factoryStrategy) {
this.fishClass = fishClass;
this.factoryStrategy = factoryStrategy;
}
public Fish create(int x, int y) {
return factoryStrategy.createFish(x, y);
}
public Class<? extends Fish> getFishClass() {
return fishClass;
}
public interface FactoryStrategy<F extends Fish> {
F createFish(int x, int y);
}
#SuppressWarnings("unchecked")
public static <F extends Fish> FactoryStrategy<F> getFactory(Class<F> fishClass) {
return FACTORY_STRATEGY_MAP.get(fishClass);
}
public static String[] names() {
return NAMES;
}
}
This enum could then be used in the following manner -
Fish fish = FishType.valueOf("BLUE_FISH").create(0, 0);
or
Fish fish = FishType.RED_FISH.create(0, 0);
or, if you need to know the type of the created fish, you can use this call -
BlueFish fish = FishType.getFactory(BlueFish.class).createFish(0, 0);
To populate the items in a menu or obtain all fish types for any other reason, you can use the names() method -
String[] names = FishType.names();
To add new types, the only code that needs to be edited is to add a new enum declaration such as
GREEN_FISH(GreenFish.class, new FactoryStrategy<GreenFish>(){
public GreenFish createFish(int x, int y) {
return new GreenFish(x, y);
}}),
It may seem like a lot of code, but it's already been written, it provides a clean API to call from other code, it provides pretty good type-safety, allows the fish implementations the flexibility to have whatever constructors or builders that they want, it should be fast performing, and it doesn't require you to pass around arbitrary string values.
If you are just really into keeping it concise, you could also use a template method in the enums -
public enum FishType {
BLUE_FISH(){
public BlueFish create(int x, int y) {
return new BlueFish(x, y);
}
},
RED_FISH(){
public RedFish create(int x, int y) {
return new RedFish();
}
};
public abstract <F extends Fish> F create(int x, int y);
}
With this, you still get a lot of the same functionality such as
Fish fish = FishType.valueOf("BLUE_FISH").create(0, 0);
and
Fish fish = FishType.RED_FISH.create(0, 0);
and even
RedFish fish = FishType.RED_FISH.create(0, 0);
Study the Factory Design Pattern. That is essentially what you are doing here, but will be a little bit cleaner if you use it explicitly.
It is not always just a giant switch statement. For instance, you may have a table of dynamically loaded assemblies and/or types, each of which have a function called "GetTypeName" and another function called "CreateInstance". You would pass a string to a factory object, which would look in the table for that typename and return the result of the CreateInstance function on that factory object.
No, this isn't reflection, people were doing this long before Java came along. This is how COM works for example.
Reflection seems to be the best solution for this issue and I am glad to have this technique in my toolbox. Here is the code that worked:
public void addFish(String s, int qt){
try{
Class<?> theClass = Class.forName("ftank." + s);
Class[] ctorArgs = {ftank.FishTank.class};
Constructor ctor = theClass.getDeclaredConstructor(ctorArgs);
for(int i=0;i<qt;i++){stock.add((Fish)ctor.newInstance(this));}
} catch (ClassNotFoundException e) {...
I had to include the package name as part of the class string. I also had to make the constructors public. I was unable to implement this solution with int arguments in the constructors but I managed to find a way around using them which was cleaner anyways. The only problem now is that I must update the array of Strings used in the JComboBox everytime
I add a new species of Fish. If anyone knows a way of having java generate a list of the names of all the classes in a package which inherit from a given base class that would be helpful. Your suggestions so far were very helpful and I am greatful.

PolyMorphic class/Polymorphism/Inner Class -Getting error message

public class PolyMorphic {
public static void main(String[] args) {
PolyMorphic.printNumber(new IntNumber(1));
PolyMorphic.printNumber(new DoubleNumber(4.54));
}
public static void printNumber(MyNumber N) {
N.print(N);
System.out.println();
}
public abstract class MyNumber{
abstract void print(MyNumber N);
}
public class IntNumber extends MyNumber{
int x;
IntNumber(){
x = 3;
}
IntNumber(int x){
this.x = x;
}
void print(MyNumber N) {
double temp = (double)x;
System.out.printf("%.2f",temp);
}
}
public class DoubleNumber extends MyNumber{
double x;
DoubleNumber(){
x = 3.23;
}
DoubleNumber(double x){
this.x = x;
}
void print(MyNumber N) {
double temp = x;
System.out.printf("%.2f",temp);
}
}
}
So I am trying to create a method in the PolyMorphic class named printNumber which is polymorphic and can print(to the console) either an intNumber with two decimal places to the right or a DoubleNumber with three decimal places to the right. Such as PolyMorphic.printNumber(new IntNumber(1));
My Problem is this:
On the Lines:
PolyMorphic.printNumber(new IntNUmber(1));
PolyMorphic.printNumber(new DoubleNumber(4.54));
This is the error message:
" No enclosing instance of type PolyMorphic is accessible. Must
qualify the allocation with an enclosing instance of type PolyMorphic
(e.g. x.new A() where x is an instance of PolyMorphic)."
It gives me it for both instances and I am confused to as why It is not working. IF someone could just point me in the right direction I would be really appreciative.
Thank you.
Your inner classes require an instance of your PolymorphicClass because of the way you declared them. However, in your case, you don't need this, so you can mark your inner classes as static:
public static class IntNumber
and
public static class DoubleNumber
This is a Java design feature.
One other solution would be to operate on an instance of PolymorphicClass:
Polymorphic p = new Polymorphic();
p.printNumber(new IntNumber(1));
p.printNumber(new DoubleNumber(4.54));
EDIT:
You also need:
public static abstract class MyNumber
Don't nest your MyNumber class and its daughters inside of Polymorphic.
Nesting classes like that is only appropriate when the nested class (MyNumber, IntNumber, DoubleNumber) is part of the implementation of the enclosing class (Polymorphic). In your case, the only relationship between the two classes is that Polymorphic is calling methods on the Number classes.
By the way, the compiler has already told you one solution to your problem, if you would take the trouble to read and understand what it said. Be grateful, for few compilers are as obliging.
Edit - why is anyone downvoting a reply that is both correct and adds additional information to that provided by other answers?

Categories