Hi, this is Mary Herberth, a private computer-science teacher (for interested high school students) by profession for over a decade now. I'd like to share the way I used to teach a bunch of my students the basics of Java that I found effective, easy and effortlessly graspable.
This was how it all started with the unorthodox procedure I'd designed:
Disclaimer: Some of the stuff used to explain a few things might be mischievous.
-------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------
Well consider me
as a ‘class’ – a LadyTeacher class. That actually means I’m like a template for
creating other ‘LadyTeacher’ objects, much like a blueprint.
And as a ‘class’,
I can have, basically, my instance variables and methods.
‘Instance variables’ are what I have, while ‘methods’ are what I can do.
Roses are red
and violets are blue,
‘Instance
Variables’ are ‘what I
have’ and ‘methods’ are ‘what I can do’.
To illustrate, my
‘qualification’, ‘experience’ and even my ‘beauty’ (which itself might be an
object of ‘Beauty’ class) are all my ‘instance variables’.
Meanwhile, some
stuff that I could do, like doTeaching(), clearDoubts(), giveTuitions() are my
methods – because I can ‘do’ them.
However, I’m not a
standalone authority teaching you here but I adhere to some norms, of say
Teachers’ Association, who mandate all teachers to implement some methods (note
the word ‘mandatory’).
So, I’m said of ‘implementing’
an ‘interface’
(Teachers’ Association) and I’m compelled to implement its methods.
(Say it mandates me to take attendance of students)
Syntactically,
public
class LadyTeacher implements TeachersAssociation {
public
void takeAttendance()
{
}
}
Wait, you might
ask what’s that ‘public’ for in ‘public void takeAttendance()’ ??
Well, imagine I’ve
got a set of methods (what I could ‘do’) and each one of them is of a different kind for me. For example,
takeAttendance() is a method I’m not much worried about and hence I don’t mind
if it’s called from outside of my class or outside of my package. So I keep it
‘public’ – “visible from anywhere”.
And this applies to methods. When it comes to variables, there are some minor
changes which I’ll explain you soon.
But imagine I’ve
got a method called checkMyAge() that returns my presentAge (a variable, what
I ‘have’). Obviously, I don’t
want an outsider to know my age (although I can fake and return ‘18’ every time
someone calls it). I’m having that method just for my internal calculations,
say to fill up some form and is supposed to be called only from my class. No
one else should be able to use it upon me.
So, I declare it ‘private’.
Also, since I’m a lady teacher, I, by default, have all
the methods
(what I could ‘do’) of a ‘Lady’, as
a Lady teacher can still deliver a baby.
This eases my task
of taking care of most of my methods just by extending ‘Lady’
class, inheriting all its methods at once (This does allow me to have my own
teacher-specific methods as well).
public
class LadyTeacher extends Lady implements TeachersAssociation{
public
void takeAttendance()
{
}
}
But wait, I’m not
just a lady, I’m an alumnus of Harvard University too, I need THEIR methods as well! Cool, I can inherit
multiple classes??
Well, it turns out
that you can’t. Java does NOT allow ‘multiple inheritance’. A class can have at
most, one superclass.
But implementing
multiple interfaces is allowed, you can use them.
Why I am not
allowed to extend multiple classes?
Well, the answer
looks pretty simple. But before we get there, let me tell you what ‘overriding
a method’ is.
As I told you, a
method is something which I ‘do’. Now if I extend a class, say
Lady class, by default I inherit all the public and protected methods (‘do’)
of the Lady class. This makes my life easier as I need not write method bodies
for washClothes(), wearABra() etc again because they are already present in my
superclass, the Lady class. But imagine, I’m such a pervert that I don’t wish
to wear a bra and hence want to return false (or null) for wearABra() method.
How could I achieve that? There comes this concept of method overriding: You
override a method by including it in your class and coding it the way you wish.
So, I override wearABra() in my class.
public
class LadyTeacher extends Lady implements TeachersAssociation{
public
void takeAttendance()
{
}
public
String wearABra()
{
return(“It’s none
of your business”);
}
}
Coming to the
previous question: Why not am I allowed to extend multiple classes?
In a line, to
avoid conflicts while calling methods. Elaborating, if I (the Teacher class)
extend two classes, say HarvardUniversity class and KennedyHighSchool class
(this was where I did my schooling) which are both in-turn extended from one
single superclass , say EducationalInstitutions class, then when any method of
this superclass (EducationalInstitutions) if overridden by both its subclasses
(HarvardUniversity and KennedyHighSchool) , say calculateGrade() method, is
called from my class (the Teacher class where that’s not overridden), then
there’s an obvious ambiguity for the JVM in deciding which of them should be
called. Single inheritance avoids this.
So what’s the
workaround?
You can implement
multiple interfaces (be careful while interpreting this, YOU CAN IMPLEMENT
MULTIPLE INTERFACES, not the methods again). This gives you a decent way of
using whatever methods you’d like to call.
Now imagine some
method (what I ‘do’) say, getExperienceInfo() which I want to be used by myself
and anyone who’s sitting in my super-class hierarchy. That’s the default
accessor, you don’t need to specify anything for them. There’s a last type of
accessor called ‘protected’ that can be called by anyone from within your
‘package’ (More on packages in next class).
But before
anything else, I’d like to tell you how the LadyTeacher objects (the
individual LadyTeacher s) are created. Every class has something called
a ‘constructor’.
When you create an instance of a class, or speaking of this context, if you
create a LadyTeacher object (an individual LadyTeacher) out of the
LadyTeacher class, it’s the constructor where the ‘creation’ happens.
This is how you
create a LadyTeacher object using its constructor typically:
LadyTeacher
missClara = new LadyTeacher(); // here missClara is the name of the LadyTeacher
object you’ve just created. Note that this is the name of the teacher variable,
not of the just created teacher.
With this, a part
of heap
is allotted to the newly created LadyTeacher
object, missClara.
We call
‘missClara’ a reference to the object freshly created.
Now to do this,
the LadyTeacher class should contain a constructor or any superclass from its
superclass hierarchy should. By default, all classes are primarily extended
from the ‘Object’ class. So if none of the classes used appear to contain
the constructor, don’t worry, Object class provides one, at least
that’s not an error, although most of the time you would be providing or using
some constructor aptly.
Okay, let’s create
a constructor
for our LadyTeacher. But wait, while
creating a new object (a new LadyTeacher in this case), one might be having
different criteria or parameters, say sometimes one wouldn’t be knowing the
teacher’s name, sometimes you do and such. To facilitate all that, you can have
multiple constructors in your class, all with the same name – the class name itself, but with
different parameters. Typically, as just mentioned, the name of the constructor
is the name of the class itself.
As illustrated
below, here there are two constructors (with the same name- the class name
itself), one of which doesn’t take any argument and the other requires the name
of the teacher. If you call the first constructor while creating a new LadyTeacher
(object), it assigns missJenkins as the name of that teacher.(Note here:
nameOfTeacher is an instance variable as I mentioned already, something I have) . On
the other hand, if you want to name your teacher yourself, you need to call the
second constructor to whom you need to pass the name, like this:
LadyTeacher missClara = new LadyTeacher(“Clara
Hatterbern”);
And this is the
class now:
public
class LadyTeacher extends Lady implements TeachersAssociation{
String nameOfTeacher;
public LadyTeacher()
{
nameOfTeacher = missJenkins;
}
public
LadyTeacher(String name1)
{
nameOfTeacher = name1;
}
public
void takeAttendance()
{
//......
}
public
String wearABra()
{
return(“It’s
none of your business”);
}
}
This particular
thing what you just saw is called “constructor overLOADING". In
general, any method can be overloaded this way keeping in mind that their signature(the
argument
list and the return value are collectively
referred as the signature of a method) should be different. In that case, it’s
referred as ‘method overLOADING’.
Now imagine you
need to know how many LadyTeachers are there in the whole of US of A.
Obviously, to be a LadyTeacher, one has to create the LadyTeacher instance. So,
understandably, the total number of LadyTeacher objects created is what we are looking for. But how do we calculate
this? Yes, we need to keep a counter. Where? Right, inside the constructor of the LadyTeacher class, because that’s where LadyTeachers are created.
But it should be done in such a way that it’s the property of the class and not of the individual objects
(individual LadyTeachers). Obviously, why should any specific LadyTeacher be
keeping the count of the total number of LadyTeachers of the country? There
come the ‘static’ variables. As told
before, ‘variables’ are those which we ‘have’. ‘static’
variables are those which are specific to a class (LadyTeacher class) rather than to the
individual objects (individual LadyTeacher s). Other way put, ‘static
variables’ are NOT the
property of any object (any LadyTeacher herself) but of the class (the LadyTeacher class, the
blueprint). So ‘static variables’
retain their values throughout and it doesn’t
get re-initialized when new objects are created (well, unless that’s not
what are looking for).
===== to be
continued in the next class =====