How do I allow vars to be accessed by any class/method? - java

import javax.swing.*;
class Person {
public String name;
public static void main(String[] args) {
new Person().enter();
}
void enter(){
Person a = new Person();
String first = JOptionPane.showInputDialog(null,"Enter your first name");
a.name = first;
new la().a();
}
}
class la{
void a(){
Person a = new Person();
System.out.println(a.name);
}
}
As you can see what I'm trying to do here is to set global var 'name' from the JOption input and to then be able to access 'name' with the new inputted var, from other classes later on. Since the workings of the classes later on depend on that var 'name'. Now I know I can simply pass these on through constructors to the relevant classes and avert this problem, but I want to know if this way is possible at all ?

You're example won't achieve what you are trying to achieve.
You create a new instance Person in Main, assign it a new, then create a new instance of la, which creates it's own instance Person
There is no coalition between these various instances.
public static void main(String args[]) {
String first = JOptionPane.showInputDialog(null,"Enter your first name");
// You should be checking the return result, but any way...
Person person = new Person();
person.name = first;
La la = new La(person);
}
public class La {
public La(Person person) {
System.out.println(person.name);
}
}

Right now by not specifying that your class is Public you are setting it as Default. Default is package private so classes in other packages will not have access to this class's public vars.
Declare the class as Public and set any global vars to Public and they will be accessible.

Related

Java Inheritance: How to override instance variables/fields from parent class?

Update: I can change the variables from being private, static, or final.
I have a parent class and a child class. I want to re-use a method in the parent class. Normally, this is as easy as super.methodFromParentClass() and you're done. However, when I do this, the method I want to re-use is using instance variable data from the Parent class, which is wrong or rather, I do not want this behavior. I have DIFFERENT initialized data in the child class that needs to get passed into the method I want to reuse. If you look at the method I want to re-use (below is just an example to make it simple, but the idea is the same), I am creating multiple objects in there that use the instance variables of the class its called in. So you can see why when I call super.methodIWantToReuse it won't work, because it will take the Parent data and pass it into the objects, even though I really want it to pass the data I initialize in the child class. My real example is also creating way more objects and I have way more instance variables, so I really want to re-use this code (DRY principle) if at all possible.
How can I get around this? Would using getters i.e. getFirstName() and overriding them in the Child class, thus using Runtime Polymorphism when I call super.methodIWantToReuse(), would grab/use the Child class instance variable data be the only way???
public class ParentClass {
private static final String firstName = "Billy Ray";
private static final String lastName = "Cyrus";
private static final int age = 58;
private static final String city = "Hunstville";
public boolean methodIWantToReuse() {
Object1 obj1 = new Object(firstName, lastName);
Object2 obj2 = new Object(age,city);
Object3 obj3 = new Object(obj1, obj2);
Object4 obj4 = new Object(obj3);
// Passing in the objects created above as argument, which have the Parent instance variable data
return someRandomMethodHere(obj4);
}
public class ChildClass {
private static final String firstName = "Miley";
private static final String lastName = "Cyrus";
private static final int age = 27;
private static final String city = "Los Angeles";
public boolean methodIWantToReuse() {
// DOESN'T WORK CORRECTLY, because ends up using the instance variable data of PARENT class, but it
// needs to use CHILD class instance variable data
super.methodIWantToReuse();
}
Your parent class instance variables are Private to that, so you can't update them from Child class. So rather you use parameterize method or create Protected setter/getter for instance variables (or protected variable itself). In you your case the variables are final so you actually can't even update them. So technically that's not possible to use child class variables in parent class.
If you update your variable to protected and remove static/final modifiers (as you mentioned in comments that you can). Before calling method from parent class, update variable data before calling super method. You can do it as below:
Approach 1 : Updating data in parent class before calling parent class method.
Parent Class:
public class ParentClass {
protected String firstName = "Billy Ray";
protected String lastName = "Cyrus";
protected int age = 58;
protected String city = "Hunstville";
public boolean methodIWantToReuse() {
// Passing in the objects created above as argument, which have the Parent
// instance variable data
Object1 obj1 = new Object(firstName, lastName);
Object2 obj2 = new Object(age,city);
Object3 obj3 = new Object(obj1, obj2);
Object4 obj4 = new Object(obj3);
return someRandomMethodHere(obj4);;
}
}
Child Class:
public class ChildClass extends ParentClass {
protected String firstName = "Miley";
protected String lastName = "Cyrus";
protected int age = 27;
protected String city = "Los Angeles";
public boolean methodIWantToReuse() {
// Update data in Parent class first
super.firstName = firstName;
super.lastName = lastName;
super.age = age;
super.city = city;
return super.methodIWantToReuse();
}
}
Approach 2 : If you want to use parameterized method to make it stateless, you can do it as below:
Parent Class:
public class ParentClass {
protected String firstName = "Billy Ray";
protected String lastName = "Cyrus";
protected int age = 58;
protected String city = "Hunstville";
public boolean methodIWantToReuse() {
return methodIWantToReuse(this.firstName, this.lastName, this.age, this.city);
}
public boolean methodIWantToReuse(String firstName, String lastName, int age, String city) {
// Passing in the objects created above as argument, which have the Parent
// instance variable data
Object1 obj1 = new Object(firstName, lastName);
Object2 obj2 = new Object(age,city);
Object3 obj3 = new Object(obj1, obj2);
Object4 obj4 = new Object(obj3);
return someRandomMethodHere(obj4);;
}
}
Child Class:
public class ChildClass extends ParentClass {
protected String firstName = "Miley";
protected String lastName = "Cyrus";
protected int age = 27;
protected String city = "Los Angeles";
public boolean methodIWantToReuse() {
// Update data in Parent class first
return super.methodIWantToReuse(this.firstName, this.lastName, this.age, this.city);
}
}
NOTE: It's not good practice to keep local variables name same as the class level variables. But kept it here same for just understanding.
You can not override fields of a class. Only methods can be overridden. In your case you have to use getters and override them in sub class.
In case you really mean instance variables instead of your static variables (or class variables) as shown in your example, you could make them accessible for your subclass by changing the access modifier and removing the final keyword.
If, however, you actually mean static variables, you cannot reassign them in each subclass as they would all share the same static variables defined by the ParentClass, meaning the last loaded class would be the only result you get by calling your ParentClass#methodIWantToReuse.
Best would be to use OOP to your advantage by instantiating new individual objects with the required arguments, and using them.
By this I mean instead of doing this:
public class Example {
public static class ParentClass {
protected String name;
protected int age;
public ParentClass() {
name = "The parent";
age = 35;
}
public String methodIWantToReuse() {
return name + " is " + age + " years old.";
}
}
public static class AChildClass extends ParentClass {
public AChildClass() {
name = "Alice";
age = 13;
}
}
public static class AnotherChildClass extends ParentClass {
public AnotherChildClass() {
name = "Bob";
age = 21;
}
}
public static void main(String[] args) {
// Prints "The parent is 35 years old."
System.out.println(new ParentClass().methodIWantToReuse());
// Prints "Alice is 13 years old."
System.out.println(new AChildClass().methodIWantToReuse());
// Prints "Bob is 21 years old."
System.out.println(new AnotherChildClass().methodIWantToReuse());
}
}
Do this:
public class Example {
public static class ParentClass {
protected String name;
protected int age;
// Variables instantiated here to not cause confusion
public ParentClass() {
name = "The parent";
age = 35;
}
public String methodIWantToReuse() {
return name + " is " + age + " years old.";
}
}
public static class ChildClass extends ParentClass {
public ChildClass(String name, int age) {
this.name = name;
this.age = age;
}
}
public static void main(String[] args) {
// Prints "The parent is 35 years old."
System.out.println(new ParentClass().methodIWantToReuse());
// Prints "Alice is 13 years old."
System.out.println(new ChildClass("Alice", 13).methodIWantToReuse());
// Prints "Bob is 21 years old."
System.out.println(new ChildClass("Bob", 21).methodIWantToReuse());
}
}
This should also be along the lines of the DRY principle, as you want to reuse your code as efficient as possible instead of coding technically the same over and over again.
As you can see, there was no need for me to override ParentClass#methodIWantToReuse or call the ChildClass' super's implementation.

ArrayList is being overwritten

I am trying to add a new train to my arraylist but upon adding the train, the existing content of the arraylist gets overwritten by the new input. This results in having only one item in the arraylist without being able to add more without overwriting the other. As I do not quite know what the source of this problem in the code is, I came looking for help here.
Within this class the train is being made:
public class RCommand extends RBaseListener {
Company mycompany = new Company("traincompany");
#Override
public void enterNewtraincommand(RParser.NewtraincommandContext ctx) {
System.out.println("Now creating new train " + ctx.getText());
mycompany.addTrainTo(new Train(ctx.getChild(2).toString()));
System.out.println(mycompany.getTrains().size());
}
}
In this class the train is supposed to be added to the list.
public class Company{
private String name;
List<Train>trains = new ArrayList<Train>();
public void addTrainTo(Train train) {
trains.add(train);
for (Train t :trains) {
System.out.println(t.getName());
}
}
}
Simply test for your class Company to see if if work
public class Test {
Company company = new Company();
public static void main(String[] args) {
Test test = new Test();
test.start();
}
private void start() {
System.out.println("IT work");
company.addTrainTo(new Train("One"));
System.out.println("End first add");
company.addTrainTo(new Train("two"));
System.out.println("End second add\n");
System.out.println("Follow example will not work");
company = new Company();
company.addTrainTo(new Train("One"));
System.out.println("End first add");
company = new Company(); // <--- create the ERROR
company.addTrainTo(new Train("two"));
System.out.println("End second add");
}
}
Suppose we have train as is:
public class Train {
private String name;
public Train(String name) {
this.name = "Train" + name;
}
public String getName() {
return name;
}
}
Output is:
IT work
Train One
End first add
Train One
Train two
End second add (it work fine)
Follow example will not work
Train One
End first add
Train two
End second add<- we miss the first train because we recreate the company instance
So it work.
So the error is not in this class Company.
Check if the caller of Company recreate the class Company before adding new train
Check class train if it has something strange (static attribute for name or similar)
Looks like new "trains" object is being created for each addition. After adding, try to print the address of "trains" object to find out for sure. You can print the address by System.out.println("trains address is: " + trains)
You did't pass for us all your code required but I think, you should create a Company constructor with your train List.
Something like that:
public class Company{
private String name;
List<Train>trains;
public Company(String name, List<Train> trains){
this.name = name;
this.trains = trains;
}
...
}
Then in your RCommand class use your new Constructor
Company mycompany = new Company(new ArrayList<Train> ,"traincompany");
And it will be fine. Your mistake in code is creating new trains list every time by calling new operator.

Java - defining unknown number of variables in an entity

I need an entity called DynamicEntity for example, in which I must define an UNKNOWN number of variables with theyr setters and getters. The variables must have a name I want to give them, so for this i got:
The main class:
public class Main {
public static void main(String[] args) {
DynamicEntity dynamic = new DynamicEntity();
dynamic.parseVariable("int");
}
}
And the DynamicEntity class:
public class DynamicEntity {
public void parseVariable(String text) {
String[] tokens = text.split("-");
String variableType = tokens[0];
String variableName = tokens[1];
if (variableType.equals("int")) {
int variableName = 0;
}
}
}
Definetly the variableName will not be accepted due to its defined already.
The thing is that i dont want the variable inside the IF to be called variableName, I want the variable to be called as the whats inside the tokens[1].
And of course creating setters and getters for every new variable added, which i have no clue what to do for this.
You can benefit from the Map structure. Where as the key you put the name of your member and as value the value for it.
A simple example of concept:
class Dynamic {
private final Map<String,Object> members = new HashMap<>();
public void setMember(String name, Object value) {
members.put(name,value);
}
public Object getMember(String name) {
return members.get(name);
}
}

setting information for arraylist with separate classes

This is possibly a simple problem but I am having issues. I have 3 classes. A Student class that contains a setmethod:
public boolean setName(String fname)
{
this.name = fname;
return true;
}
A TestClass with a main that passes a string to the setmethod
static Student action;
public static void main(String[] args)
{
action.setName("John");
}
and a Classroom class that contains an add student method.
public boolean add(Student newStudent)
{
???
return true;
}
I know how to create and add an object to an array list but I am confused as to how to do it using 3 separate classes. My array list init is:
List<Student> studentList = new ArrayList<Student>();
How would I associate the attributes(name in this case) being set in the Student class to a new object being created in the Classroom class?
I think you should follow the principle of least surprise i.e., make sure the methods you create do exactly what you need them to. In your example, your setName and add methods return a boolean for some reason. Typically, setter methods don't return booleans, unless you're doing some sort of a DB insert like operation and want to make sure that your object was actually inserted.
Also, a typical idiom would be to create the controller object (i.e., TestClass) in the static main method and then initialize whatever is necessary in its constructor or by calling methods on the created TestClass object inside the main method itself.
Here's a solution.
public class TestClass {
private Classroom c;
public TestClass() {
c = new Classroom();
private Student s = new Student();
s.setName("John");
c.add(s);
}
public static void main(String[] args)
{
new TestClass();
}
}
public Classroom {
private List<Student> studentList;
public Classroom() {
studentList = new ArrayList<Student>();
}
public boolean add(Student newStudent) {
studentList.add(newStudent);
return true; //not sure why you're returning booleans
}
}
Your student class looks good, your classroom class should contain a list of students, and ways to add/remove/list students. Your test class should create new students which you can then add to your classroom.
I assume you want a Test Class which is a test event like midterm or final, and you want to put Student and ClassRoom in the Test Class.
So you get three classes, and they're all related. If this is the case you want, then you can do this. (This is a very simplified version!!)
class Test{
String name;
HashMap<ClassRoom, ArrayList<Student> > roomMap;
// ... other functions
}
// you can use ClassRoom as key and Student list as value.
// A ClassRoom key will return a value which is a Student list containg students who are going to take a test in that room.
public static void main(String[] args) {
Test test = new Test();
test.name = "MidTerm";
test.roomMap = new HashMap<ClassRoom, ArrayList<Student> >();
ArrayList<Student> students = new ArrayList<Student>();
students.add(new Student("John"));
students.add(new Student("Mark"));
ClassRoom room = new Room("R123");
test.roomMap.put(room, student);
// If there are a lot of test, then you could manage test in an ArrayList in your main.
ArrayList<Test> testList = new ArrayList<Test> ();
testList.add(test);
}
Maybe you could give more details of your requirement.

a little programa to create people

I want to make a program to create people and to show a list of such persons, but do not know if I am doing well and neither logic using "arraylist" to print the results anyone can help me? Thank you very much.
package person;
import java.util.*;
public class Person {
public int Id;
public String Name;
public boolean Show;
public ArrayList people;
public Person(
int identificator,
String thename,
boolean showornot
){
this.Id = identificator;
this.Name = thename;
this.Show = showornot;
}
public void InsertPerson(Person person, ArrayList list){
this.people = list;
list.add(person);
}
}
The main:
package person;
import java.util.*;
public class Trying {
public static void main(String[] args) {
Scanner stdin = new Scanner(System.in);
Scanner stdin2 = new Scanner(System.in);
Scanner stdin3 = new Scanner(System.in);
Scanner stdin4 = new Scanner(System.in);
ArrayList list_of_people;
list_of_people = new ArrayList();
int option = 0;
int identificador = 0;
String name = "";
boolean show = true;
name = “Toni”;
Person person1 = new Person(identificador, name, true);
person1.InsertPerson (person1, list_of_people);
Iterator ite = list_of_people.iterator();
while(ite.hasNext()){
System.out.println(list_of_people);
}
}
Thanks!
Problem: You are creating the arraylist "people" as a property of each "person" (Saying, each person has a list of people)
Quickfix:
Move public ArrayList people; to your Trying class.
Move public void InsertPerson(Person person, ArrayList list) to your Trying class as well.
Better fix:
I recommend using a PeopleManager class - which contains the arraylist "people" and the InsertPerson method. Then, you use the PeopleManager in Trying to build your people list.
public class PersonManager
{
ArrayList<Person> people;
public PersonManager()
{
people = new ArrayList<Person>();
}
public void InsertPerson(Person person)
{
people.add(person);
}
}
Then, you can remove the arraylist from Person, and the method InsertPerson from Person. You'll need to create a PersonManager in your Trying class.
public ArrayList people; does not belong in the Person class. I would suggest using it your client code (the Trying class) or creating a class People that inherits from ArrayList. You can then add a InsertPerson function to that class if you wish.
I would also suggest using a ArrayList for your collection rather than an ArrayList. See a generic collections tutorial here. You should also create getter/setter moethods instead of using public fields.
So, your classes would be:
public class Person { // ...
public class People extends ArrayList<Person> {
public void InsertPerson(Person person) {
this.add(person);
}
// ...
What everyone else is saying is true, but I think theoretically your code should still work. There is a problem with this line however...
while(ite.hasNext()){
System.out.println(list_of_people);
}
You are outputting the whole list every iteration and probably infinite looping. Change it to something like this...
while(ite.hasNext()){
Person curPerson = (Person)ite.next();
System.out.println(curPerson.Name);
}
A slightly more elegant solution is to ditch the iterator for a foreach loop...
for (Person person : list_of_people) {
System.out.println(person.Name);
}

Categories

Resources