5

I am calling a method from a class and it gives me an error to make the method static. I am confused about why, as I asked this question What's the difference between a class variable and a parameter in a constructor? and my understanding was that class variables were made static.

Patient class:

public  String  setOption(String option) throws IOException
{
        option = stdin.readLine();
        //stuff here
    return option;
}

Patient management system:

public class PatientManagementSystem
{
    static BufferedReader stdin = new BufferedReader(new InputStreamReader(
            System.in));
    public static void main(String[] args) throws IOException
    {
        Patient.setOption(null);    
    }
}

The error:
enter image description here

Do I change the method to static or create a local variable?

Community
  • 1
  • 1
  • 1
    The suggestion to change the method to `static` is wrong: it is based on the assumption that your call is correct, but it isn't. – Sergey Kalinichenko Nov 06 '13 at 13:14
  • Note that calling `setOption` without doing something with its return value has no effect at all. – tobias_k Nov 06 '13 at 13:15
  • Hard to tell without seeing your Patient class. Probably you have some attribute like `option`. then `setOption` should just set that option to the value passed as a parameter. The reading from stdin should not be done in the setter. – tobias_k Nov 06 '13 at 13:22
  • Instead of describing your error, better tell us what exactly you want to achieve. – tobias_k Nov 06 '13 at 13:27
  • Which IDE is making this suggestion? – Raedwald Nov 13 '13 at 08:01

9 Answers9

6

Based on your earlier question, I think may not be fully digging the concept of the local variable. In this method:

public String setOption(String option) throws IOException
{
    option = stdin.readLine();
    return option;
}

option is a local variable. You pass the initial value for that variable as an argument to the setOption method each time you call it (and you happen to ignore that value), but with that detail out of the way, this is the same as

public String setOption() throws Exception
{
    String option = stdin.readLine();
    return option;
}

Now, local variables are something completely different from instance or class variables: they are valid only within a method body, and exist only during the time that method is executing. With that in mind, let's look at this code:

static BufferedReader stdin = new BufferedReader(new InputStreamReader(
        System.in));
public static void main(String[] args) throws IOException
{
    Patient.setOption(null);    
}

Here you are basically misusing a class variable stdin for something which should have been a local variable:

public static void main(String[] args) throws IOException
{
    BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
    Patient.setOption(null);    
}

On to the question of your method call... setOption is currently an instance method, which means it must be called in the context of an instance. You are calling it as-is, with no instances of Patient involved. If you continue down this road, you won't be able to represent more than a single patient, probably not your idea. So you want to keep the method as it is and create an instance of Patient:

Patient p = new Patient();
p.setOption(...);

In your overall design it is not clear what role setOption should play, but it is not a good idea that it uses the static stdin variable (I already made it local above). You want to pass any data read from stdin into the setOption method and thus decouple it from the input reading logic.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • you want the user to say "i want setOption to be called"? That should definitely not be decided within `setOption` but within `main`, which should read and interpret user input and call the appropriate method. – Marko Topolnik Nov 06 '13 at 13:31
5

You (probably) need to create an object of the Patient class.

Patient myPatient = new Patient();
myPatient.setOption(null);

It's hard to necessarily know what you want to do with such limited information. I don't know what you intend to do with the Patient class, but my best guess? It makes sense to do it this way, given you're trying to call a method with a setter naming convention.

If you don't intend to instantiate an object and go the route of making setOption a static method, then you should probably change the method name.


With a more in-depth explanation of what exactly you're trying to accomplish (not even talking pseudo-code, just a very abstract idea of what you're trying to do), it would be easier to explain more about static here (with your specific example) and what you should be doing, etc.

nhgrif
  • 61,578
  • 25
  • 134
  • 173
  • @Skippy-psI'mawoman Then all you need to do is just call your constructor (whether default or otherwise), as I've done in my answer to instantiate an object. Then call `setOption(null)` on that instantiated object. – nhgrif Nov 06 '13 at 14:48
3

Do I change the method to static or create a local variable?

Both is OK.

If your method doesn't use class variables, it's better to make it static, so you do not have to instantiate the class for the method call.

VladL
  • 12,769
  • 10
  • 63
  • 83
3

The question of when to make something static vs. non-static is based on the real-world object/concept being modeled. Let's take the example of the Patient object in this code. Without seeing any code about the Patient, it's still pretty clear what a Patient is and what it represents. So, at its simplest:

  • If you're doing something with a particular Patient (let's say Jane Doe), then it's not static. It's operating on an instance of a Patient.
  • If you're doing something regarding the concept of a Patient, then it's static.

So some non-static operations might be:

  • Update the Patient's name
  • Admit/discharge the Patient from a hospital
  • Transfer the Patient to a different Doctor

All of these would involve a specific Patient, which would have been initialized somewhere:

var janeDoe = new Patient("Jane Doe");
// ...
janeDoe.TransferTo(doctorSmith);

I'm actually having trouble thinking of some static methods for a Patient. The most common example of a static method is probably a factory method, where you get an existing Patient or collection of Patients. Something like:

var janeDoe = Patient.Fetch("Jane Doe");

or:

var todaysPatients = Patient.Fetch(DateTime.Today);

Various helper methods are often static as well, perhaps a method on the Patient object which accepts a MedicalRecord object and converts it to a different format, for example.

But the overall idea is the same. If you're interacting with a specific instance of an object, then you need an instance of that object to represent that real-world concept.

David
  • 208,112
  • 36
  • 198
  • 279
  • 1
    @Skippy-psI'mawoman: Without more context, it sounds like this functionality isn't meant to be part of the `Patient` object at all, honestly. Getting user input is an application concern. The `Patient` object should really be focusing only on what a `Patient` does, which doesn't include getting user input. For one thing, this would "tightly couple" the `Patient` class with a specific input/output scenario, which isn't a good thing. More specifically, all this method is doing is getting input and returning it. It's not doing anything related to a `Patient`. – David Nov 06 '13 at 13:31
  • 1
    @Skippy-psI'mawoman: Don't sweat it, object oriented programming takes practice like anything else does. In something like this (again, knowing *very little* about the overall system) I'd probably create an object whose sole purpose is to interact with the user, displaying output and collecting input. That object may then interact with instances of the `Patient` object for managing the state of the system. For a lot more information than I can give, look up the "S.O.L.I.D." principles of object oriented design. They serve as very helpful guidelines for creating objects. – David Nov 06 '13 at 13:39
2

Because you are directly calling that method without creating object of class.

When to have static methods?

Community
  • 1
  • 1
Shoaib Chikate
  • 8,665
  • 12
  • 47
  • 70
2

To call a method in a static way, you have to make it static :

public static String  setOption(String option) throws IOException

But in your example if stdin is not a static member of your Patient class, it can't work.

To sum up, you can call a method the way you call it when it's declared static. In a static method you can access only static members of your class.

Julien
  • 2,544
  • 1
  • 20
  • 25
2

Try this in your main method :

Patient myPatient = new Patient();
myPatient.setOption(null);
Lukas Warsitz
  • 1,231
  • 1
  • 11
  • 20
2

We create classes with static methods when we intend to use those methods as utility methods, like parseInt in the class Integer. thus either modify the method

public static String  setOption(String option) throws IOException // STATIC
{
    option = stdin.readLine();
    //stuff here
    return option;
}

and then use the method like

    Patient.setOption(null);    

OR instantiate an object for Patient like

    Patient obj = new Patient();
    obj.setOption(null);    
Ankit Rustagi
  • 5,539
  • 12
  • 39
  • 70
2

In Java main method is special. It's the starting point of your code. Static methods could be called from anywhere in your code. Thus actually it does not belong to the containing class. It's also true for the main method.

Thus you should construct your object in the main method and then use the constructed instance's methods. If you do not construct your an instance, then your ide will recognise the error and suggest you to make it static.

scriptmonster
  • 2,741
  • 21
  • 29
  • Nope. Actually if the setOption method sets an attribute of Patient class, you should write setOption method inside Patient class. At this stage you just stick to not using static methods except main method. Since they are like individual methods which needs classes only for naming. Try to write everything normal. Static values are used for general methods and attributes which are commonly used at different classes. – scriptmonster Nov 06 '13 at 14:35