Scope
Scope is a fundamental concept in programming. It refers to the accessibility of named entities in our code.
In this topic, we will look at:
- The different types of named entities in our code.
- The scope of these named entities.
- The nesting of scope within our code.
- The rules for accessing named entities.
Named entities
Our programs will always be full of named entities, such as:
- method names (e.g.
main()
,getAge()
), - variable (and field) names (e.g.
bob
,age
), - type names (e.g.
Person
,String
,int
), etc.
For this topic on scope, we are just going to look at the first two (methods and variables+fields).
Scope of named entities
When we talk about the scope (of a method or variable), we are talking about its “accessibility”.
In other words, from which part(s) of our code can we access that named entity?
- Something “in scope” may be accessed.
- Something “not in scope” cannot be accessed.
Consider the following bit of code:
public class Course {
private String name;
private int cap;
private ArrayList<String> students;
private static int nextID = 0;
public Course(String name, int max) {
int foo = 23;
...
}
public boolean enroll(String studentID) {
int bar = 45;
...
}
public static int getNumberOfCourses(boolean onlyActive) {
String bar = null;
...
}
}
1. If we are inside the Course()
constructor, what’s in scope?
- All fields:
name
(instance field)cap
(instance field)students
(instance field)nextID
(static field)
- All local variables:
name
(parameter)max
(parameter)foo
(locally-declared variable)
- All methods:
enroll()
(instance method)getNumberOfCourses()
(static method)
2. If we are inside the enroll()
instance method, what’s in scope?
- All fields:
name
(instance field)cap
(instance field)students
(instance field)nextID
(static field)
- All local variables:
studentID
(parameter)bar
(the locally-declared variable insideenroll()
)
- All methods:
enroll()
(instance method – i.e. itself for recursion)getNumberOfCourses()
(static method)
3. If we are inside the getNumberOfCourses()
static method, what’s in scope?
- Only
static
fields:nextID
(static field)
- All local variables:
onlyActive
(parameter)bar
(the locally-declared variable insidegetNumberOfCourses()
)
- Only
static
methods:getNumberOfCourses()
(static method – i.e. itself for recursion)
Nesting scope
Above we talked about scope across methods/constructors.
But we can also talk about scope within a method/constructor, which is defined by the nested { ... }
blocks:
public class Course {
private String name;
private int cap;
private ArrayList<String> students;
...
public boolean enroll(String studentID) {
int bar = 45;
String name = "Local variable for fun";
// Check there's space
if (students.size() < cap) {
// Print current students
for (String id: students) {
System.out.println(id);
}
// Check not already enrolled
for (String id: students) {
if (studentID.equals(id)) {
boolean result = false;
return result;
}
}
// Not already enrolled in the course, so enroll them
students.add(studentID);
boolean result = true;
return result;
} else {
// No space in course
boolean result = false;
return result;
}
}
...
}
We can visualise the nesting of our scopes (for the enroll()
method) as follows:
To keep the diagram tidy, not all possible arrows are drawn. But in a nutshell, the general rules are:
All fields❊ may be accessed from anywhere in any of the method/constructor scopes.
All fields❊ may be accessed from anywhere in any of the nested block scopes.
Parameters may be accessed from anywhere in respective method/constructor scope (including nested block scopes).
Local variables may be accessed after they have been declared.
Local variables cannot be accessed before they have been declared.
Local variables cannot be accessed from an outer scope.
Local variables cannot be accessed between block scopes that are not nested.
Local variables and parameters cannot be accessed from another method.
❊ Of course, the usual rules concerning static
fields/methods also need to be observed.