Gaps in Java knowledge but can't find the direction to search - java

===================================================================================================
UPDATE:
My problem was that I did not know that classes can indeed communicate with each other. For example, you can create 2 classes, instantiate an object of each class in your program, and then actually pass one object into the other. This not only directly solved my problem, it opens an entire world of possibilities for the future.
public class FirstClass {
int valueToPass = 100;
void methodToPass(){
//do stuff
return;
}
}
public class SecondClass {
FirstClass passedInObject;
int valueFromOtherClass = passedObject.valueToPass;
return;
}
}
===================================================================================================
I understand a class is a blueprint of attributes and actions that can be instantiated as an object.
I understand an inner class is a non static class defined within another class and has access to the outer class' data.
I understand a child class is a separate file defining a class that does not have access to its parent's data.
So I've got my main activity class of an Android application. I'm just making a simple dice game to help tie up all the loose ends. I've defined the follow child classes in separate .java files:
Dice
ScoreCard
I instantiate an array of 5 Dice objects and 1 ScoreCard object and attach those objects to a "view" in the android OS's window, then assign an action method to that view with the set click listener method inside the object. The objects work flawlessly. I can click the dice and they will hold and unhold themselves, roll, and update their own views. I can of course access the value of the dice from my main class by referencing their object.value variable. (I understand that accessors are presumed by many to be superior to directly interacting directly with a child class' variables, this app is just to solidify conceptual ideas of the overall flow of an application) I can click a slot on the scoresheet and it will toggle the highlight that slot as the slot to assign the score to. The scorecard object also updates the entire scorecard on the screen after each interaction.
So far so good, everything is working great, and I understand everything that is going on.
However, in my main activity class, I now want to create a roll function, and assign that function to the click listener for the roll button. That works, however, when assigning a function to the click listener, you can not reference any non final variables because the click listener of a given view actually instantiates an anonymous object (anonymous class?) of the View class and overrides the onclick method with its own, therefore you can not reference any non final variables from an inner class defined in another method. In other words, you can't pass the function you assign to the click listener any values from your main class, and although I do not understand why, the roll function I created can not access the main class' variables directly.
There is the first gap in my knowledge, and I've read dozens of tutorials, watched dozen's of videos, but I don't know why my roll function can't see the variables.
public mainclass extends otherclass {
#override
otherclass.method {
// where my application starts
int a=7;
roll();
}
void roll(){
int funcVar = a;
return;
{
}
Eclipse says that a can not be resolved.
I try to make a public thinking that might allow the function to see it, but if I change
int a=7;
to
public int a=7;
then Eclipse says that it can't be public, only final.
A way around this is to create a new child class called Roll, or perhaps ActionButton to use it for other buttons in the future, just as I did with the ScoreCard and Dice classes. This works great, in so far as I can instantiate a roll button object, assign a view to the object and then set the click listener to one of the object's methods. However, this transfers the functionality of my rollbutton from my MainActivity class to my RollButton class, which doesn't have access to the data in my dice and scorecard objects. In other words, I can't figure out how to make my child classes talk to each other, I don't really think they are even supposed to. I imagine the main class is supposed to access each child class independently, but if that's the case then I'm not really sure what I'm supposed to do at this point.
The only solution I can think of is to put all those child classes into the same child class, DiceGame, and pretty much just use the MainActivity class to instantiate an object of the DiceGame class and transfer processing entirely over to that object. While that would work, all the methods in the class would have access to all the data in the class, it seems to contradict the entire purpose of object oriented programming.
Is this all so messed up because of the way the click listener in android apps is assigned through instantiating an anonymous inner class that can't access any non final variables, or I just missing a key concept in the way Java applications are structured?
I'm sorry this is so long, but I really couldn't shorten it and still convey the entire problem.
-------edit----------
public class MainActivity extends Activity {
public int a=7;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
// my application starts here
Dice[] gameDice = new Dice[6];
for (int i=1;i<6;i++) gameDice[i]= new Dice();
for (int i = 1; i<6 ; i++){
gameDice[i].dieView = (ImageView) findViewById(R.id.die1 + (i-1));
gameDice[i].setListener();
}
int[] slotId = new int[] {R.id.val1,
R.id.val1,R.id.val2,R.id.val3,R.id.val4,R.id.val5,
R.id.val6,R.id.valsubtotal,R.id.valbonus,
R.id.val3k,R.id.val4k,R.id.val5k,R.id.valfh,
R.id.valsmstr,R.id.valstr,R.id.valdicey,R.id.valtotal
};
ScoreCard scoreCard = new ScoreCard();
scoreCard.NUMBER_OF_SLOTS = slotId.length;
for (int i=1 ; i<scoreCard.NUMBER_OF_SLOTS ; i++){
scoreCard.slotView[i]=(TextView) findViewById(slotId[i]);
if (i!=8 && i!=15) scoreCard.setListener(i);
}
scoreCard.initScoreCard();
rollButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
roll();
}
});
}// end of overridden method
void roll(){
//do stuff
int funcVar = a; // can totally see a now that it is higher scope
return;
}
}//end of class
The suggestion to increase the scope of a did in fact work. However, a is just an example I was using for simplicity's sake. I really need to access those data contained in the objects I instantiated, and if I instantiate them in a higher scope the application abruptly ends upon launch.

Perhaps the confusion is between a variable and a field. A field is a property that is associated with an object. A variable exists only in the context of a method. When the method finishes, the variable vanishes.
A field, on the other hand, looks exactly the same as a variable except that a field is declared outside of any method, directly on the class "body". Fields and methods are declared at the same hierarchical level. You can see that on Eclipse. Check the "outline" view.
If you need several methods to read and write the same "variable", then what you need is a field. I hope this clarifies.

Variables can have different scopes:
public class MyClass {
static int a; // variable bound to class MyClass, seen from all instances
int b; // variable bound to instance, each instance of MyClass has its own value
public void foo(int c) { // parameter variable: local
int d; // local variable
}
}
Local variables in a method are visible only within the same method invocation (so each time foo() is invoked, new local variables are used).
Values can be passed indirectly by storing them in instance or class variables (global variables), but that's ugly and error prone. The better variant is to pass the values as method arguments, this works well with multiple invocations and also multiple Threads, and removes the side effects you'd have when passing values using global variables.
In your example, just pass the value of a to your method:
public mainclass extends otherclass {
#override
otherclass.method {
// where my application starts
int a=7;
roll(a);
}
void roll(int funcVar){
// funcVar is whatever value was passed, here: 7
return;
{
}

Related

Referencing instance variables from within abstract class

I have an abstract class which lays out what each of its subclasses should implement. Most methods will have different implementations for each subclass, but some will be the same for all. I want the methods that will be the same to be to be defined in the abstract class, so that I'm not pasting the same method into several different classes. However, when I call that method on an instance of the abstract's subclass, I receive a nullpointer because, I imagine, the method implemented in the abstract class is referencing the abstract's field, not the instance's field.
Can someone point out where the flaw is?
For example:
abstract class ControlView {
String[] controls;
abstract void render();
void release() {
for (int i = 0; i <= controls.length; i++) {
//Release the controls
}
}
}
class StartingControls extends ControlView{
String[] controls;
Button uiDrawButton;
Button uiLoadButton;
StartingControls() {
this.controls = new String[2];
uiDrawButton = new Button();
this.controls[0] = uiDrawButton;
uiLoadButton = new Button();
this.controls[1] = uiLoadButton;
}
public void render() {
//Unique Render implementation
}
}
When I call
instanceOfStartingControls.release();
I obviously want to iterate over the two strings that I put into instanceOfStartingControls' controls field when it was constructed. I do not want to iterate over the non-initialized array that is apparently living in the abstract.
Is it some combination of access modifiers or static methods that is keeping this from working as it seems it should, or am I missing some crucial bit of knowledge on abstract classes? This feels like a basic question, but I'm having a hard time putting it to words, so I've not been satisfied with any results from my searches.
There are two arrays called controls. The one in the derived class is obscuring the one in the base class, thus the base instance never gets set non-null.
Delete the declaration from the derived class.
This issue is not related to the base being abstract. If you use the same field name in a derived class as is used in a base class, the base instance will be obscured.

How to use a Get method in java

A ton of questions have been asked on how to create getter and setter methods in java. But i have yet to see one that actually tells me how to use it.
Say i have Private int i = 1; in class A and i want to access it in class B.
I would first create a get method in class A called getIntI(); which would return the value of i.
Then in class B if i wanted to create an if statement that would need the value of i how would I get int i's value. The following is my try and calling the get method which does not work.
if(getIntI == 1)
{System.out.print.ln("int i is one");}
It is probably a really stupid question but i cant find an answer for it elsewhere.
In class A:
public int getIntI(){
return i;
}
Note: Now since your variable is single character named (just I), getter method is named getIntI since the name getI makes lesser sense. But generally, getter methods are something like get+VariableName and do not involve mentioning type. For example if I had a variable called int count, my method would be named getCount instead of getIntCount. Thats the general convention.
Also, naming variables in single char formats (like x, y etc) is discouraged because it may create confusion and management difficulty in complex programs. Though in very small programs they are fine.
Moving back to topic, if you want to access method getIntI() in class B, you will either have to inherit class A or create an object of class A reference to its method.
For class B:
Creating object
A obj = new A();
if(obj.getIntI() == 1)
// Do stuff
Inheriting class A:
public class B extends A{
... // Your stuff
if(getIntI() == 1)
// Do stuff
... // Your stuff
}
Of course there are other ways but these are simpler ones.
if class B extends class A then do only this changes,
if(getIntI() == 1)
If above inheritance was not there then do this,
if(new A().getIntI() == 1)
The problem is that you need to create a object derived from class A before you can access its variables/methods using
A a = new A();
where "a" is the name of the object. Then you can access the getter method by calling a.getIntI. You can also declare the int variable as static so that you wouldn't have to instantiate any objects. An example of class A with the static variable and getter method would be:
public class A {
private static int i = 1;
public static int getIntI() {
return i;
}
}
With this, you can call the getter method with A.getIntI().
First, if you want to access one of A's non-static methods (in this case, getIntI), you need an instance of A, or you can just declare it static.
Secondly, A method call needs a parameter list, even an empty one is needed. getIntI does not need any parameters, so you should add () at the end.
Now, you can get an instance of A somewhere and call it aObj. Andd then you can use it in the if statement:
if (aObj.getIntI == 1)
And remember to add ()!
if (aObj.getIntI() == 1)
Alternatively, you can declare i in A as static. There are two main differences between a static and a non-static variable.
You don't need an instance of the declaring class to access the static variable.
Unlike non-static variables, there is only one static variable. If you have a non-static variable i, you can create lots of instances of A and each instance will have its own i
Now let's see this in action, declare i as static:
public class A {
private static int i = 1;
public static int getIntI () { return i; }
}
Note how both i and getIntI are declared static.
Then you can use in a if statement like this:
if (A.getIntI() == 1)
Note how I use the class name A to access the method, not an instance of A.

Keeping track of all instances of a subclass in the superclass

I have the following, stripped-down Java code:
// Class, in it's own file
import java.util.*;
public class Superclass {
protected List<Subclass> instances = new ArrayList<>();
public class Subclass extends Superclass {
private int someField;
public Subclass(int someValue) {
this.someField = someValue;
updateSuperclass();
}
private void updateSuperclass() {
super.instances.add(this);
}
}
}
// Implementation, somewhere else, everything has been imported properly
Superclass big = new Superclass();
Subclass little1 = big.new Subclass(1);
Subclass little2 = big.new Subclass(2);
Subclass little3 = big.new Subclass(3);
I want to implement a method in Superclass to do something with all the Subclasses. When a Subclass is created, it should add itself to a list in Superclass, but whenever I try to loop through that list in Superclass, it says the size is 1. The first element in the list (instances.get(0)) just spits out a String with all the proper information, but not in object form, and not separately. It's like every time I go to add to the list, it gets appended to the first (or zeroeth) element in String form.
How can I solve this so I can maintain an ArrayList of Subclasses to later loop over and run methods from? I'm definitely a beginner at Java, which doesn't help my case.
If all you need is a count then I suggest a static value that is updated in the constructor of the parent class.
private static int instanceCount = 0;
public Constructor() {
instanceCount++;
}
If you absolutely need every instance in a list so you can do something with them then I recommend you strongly re-consider your design.
You can always create a utility class that will let you maintain the list of objects to run processes on. It's more "Object Oriented" that way. You can also create one class that has all of the operations and then a simpler bean class that has only the data values.
But, if you insist, you can still use the same technique.
private static List<SuperClass> list = new LinkedList<SuperClass>;
public Constructor() {
list.add(this)
}
Each instance gets its own copy of your superclass's variables.
What you want to do is make the variable "static" by putting the static keyword before it. You probably don't even need the superclass accomplish what you're trying to do.

Calling a specific member of an object array from another class-method

I am now working on the AI section of my project. I am calling a method from my AI class which is intended to calculate where the Gladiator objects I have drawn need to actually end up. I passed to that method a List containing all my objects I want to place. A previous method from the AI class has determined where they want to be from each other, distance-wise and I have stored it as gladiator[0..1..2..etc].movementGoal.
Although the project is not real time, ie I will want to just "step" through it in the end, I do want simultaneous movement to occur. This means that my standard method of iterating through the list will not work as I need information about the other Gladiator's movement decisions in order to figure out any one Gladiator's actual movement as these decisions interact.
How can I access another specific gladiator's variables when I am outside the class and only have them in List form?
Edit:
I guess I could iterate through and test for a variable gladiatorNumber to be correct, then when it is pull that info? That would be pretty round-about but its all I can think of.
Edit2:
As requested, some code. My method in Ai class looks like this:
public void moveAI(List<Gladiator> gladiators) {
My gladiator is defined as such:
public class Gladiator {
Gladiator class is created as an array then added into a list in a separate main class. I don't really want to include more code than this, as there is a ton of it. Basically it boils down to how can I call gladiator[0] from AI class even though I created said object in the main class and only have them in list form in the AI class. Assume all variables in Gladiator are public. The error I am getting is cannot find symbol referring to gladiator[0...1...2...etc].
I think your problem boils down to wanting to pass the arrays of gladiators to another class. That should be fairly easy. If you in your main-class have these two defintions (note you only need one, I recommend the list as it is more versatile, arrays have fixed-length).
You want something like this:
public class Main {
// ....stuff
// This is the main class that keeps the list of gladiators
private List<Gladiator> gladiatorsList;
private Gladiator[] gladiatorsArray;
private MovementAI movementAI;
public Main() {
// You initialize gladiatorsList and gladiatorsArray as before
// gladiatorsList = ...
// gladiatorsArrray = ...
// Now you want to pass this list/array to another class (the AI), you
// can do this in the constructor of that class like so:
movementAI = new MovementAI(gladiatorsList);
}
// ...stuff as before
}
The AI
public class MovementAI {
private List<Gladiator> gladiators;
// Giving the class the list-reference, this list will be the same as the
// list in main, when main-list changes so does this one, they point to the
// same list-object, so the reference is only needed once.
public MovementAI(List<Gladiator> gladiatorsList) {
this.gladiators = gladiatorsList;
}
// The class already has a reference to the list from its constructor so it
// doesn't need the list again as a parameter
public void moveAI() {
}
// If you don't want to keep a reference to the list in this class but only
// use it in a method (I would not recommend this)
public MovementAI() {
}
// You need to pass it gladiatorsList everytime you call this method.
public void moveAI(List<Gladiator> gladiators) {
}
}
I see in your last comment that you have decided to let the AI decide to repaint if it meets a criteria, that is not recommended, you should keep responsibilities separate in your classes, less error-prone and better development. It is recommended to let the AI change the list of gladiators (move them, kill them etc) and the rendererclass simply paint every gladiator.
It also seems you want to have every gladiator be able to hold another gladiator as a target, it is better for them to hold the target as an Object, this way you don't have to search the entire list to find out which gladiator the gladiatornumber refers to and you don't have to think about ordering in the list. Something like this:
public class Gladiator {
// ..other stuff
private Gladiator target;
public Gladiator getTarget() {
return target;
}
public void setTarget(Gladiator target) {
this.target = target;
}
}

Why am I able to call private method?

I should not be able to invoke a private method of an instantiated object. I wonder why the code below works.
public class SimpleApp2 {
/**
* #param args
*/
private int var1;
public static void main(String[] args) {
SimpleApp2 s = new SimpleApp2();
s.method1(); // interesting?!
}
private void method1() {
System.out.println("this is method1");
this.method2(); // this is ok
SimpleApp2 s2 = new SimpleApp2();
s2.method2(); // interesting?!
System.out.println(s2.var1); // interesting?!
}
private void method2() {
this.var1 = 10;
System.out.println("this is method2");
}
}
I understand that a private method is accessible from within the class. But if a method inside a class instantiate an object of that same class, shouldn't the scope rules apply to that instantiated object?
Can static method like main access the non-static member of the class, as given in this example ?
Your main method is a method of SimpleApp, so it can call SimpleApp's private methods.
Just because it's a static method doesn't prevent it behaving like a method for the purposes of public, private etc. private only prevents methods of other classes from accessing SimpleApp's methods.
Because main is also a member of SimpleApp.
See below chart
Access Modifiers
**Same Class Same Package Subclass Other packages**
**public** Y Y Y Y
**protected** Y Y Y N
**no access modifier** Y Y N N
**private** Y N N N
As your method is inside car it's accessible based on above thumb rule.
From the Java Tutorial:
private modifier—the field is accessible only within its own class
The main method is inside the same class as the private method and thus has access to it.
private means "only stuff in this class can mess around with it". It doesn't mean "only this instance can call its methods", which seems to be what you're expecting. Any code in SimpleApp can use anything in any SimpleApp. The alternative would be to break encapsulation -- how would you make a proper equals method, for example, that didn't require access to another instance's fields, without making those fields protected or even public or requiring getters for data that should only be available inside the class?
The call you issue is from within the same class where your private method resides. This is allowed. This is the way 'private' is defined in java.
In the program, we created two instances of the class by using which we called two private methods. It's a kind of interesting to see this works is that this is the way we used to call public or default methods outside its class using object reference. In this case, it's all done inside the class definition, so it's valid. The same code put outside the class will result in error.
Because the private scope limits access to the class defining the method, and your main happens to be in the same class.
private modifier—the field is accessible only within its own class.
See Access Modifiers in the Java Documentation.

Categories

Resources