java:defining_classes_in_java
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionLast revisionBoth sides next revision | ||
java:defining_classes_in_java [2020/09/12 01:21] – [Mutators] mithat | java:defining_classes_in_java [2020/09/12 03:32] – [Instantiation and use] mithat | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== | + | ====== |
We are going to write a simple class for implementing a counter similar to one of these: | We are going to write a simple class for implementing a counter similar to one of these: | ||
Line 28: | Line 28: | ||
Here's a Java definition for a '' | Here's a Java definition for a '' | ||
- | <file java ClickerCounter.java> | + | <code java> |
public class ClickerCounter { | public class ClickerCounter { | ||
| | ||
Line 41: | Line 41: | ||
} | } | ||
} | } | ||
- | </file> | + | </code> |
- | In Java, class definitions need to go in their own files, and the files need to be called the name of the class with the '' | + | I have deliberately not used any comments in the definition so you can more easily see the code. |
- | In the above, '' | + | In the above, '' |
- | ==== Instantiation and use ==== | + | In actuality, this is a pretty crappy class definition for reasons we'll see later. But for now it's enough to get us started. |
- | The above is just a class definition. It doesn' | + | +==== Instantiation and use ====+ |
- | The program | + | The above is just a class definition. It doesn' |
- | <file java ClickerExample.java> | + | <code java> |
- | public class ClickerExample { | + | var myCounter = new ClickerCounter(); |
+ | myCounter.reset(); | ||
+ | myCounter.click(); | ||
+ | System.out.println(myCounter.count); | ||
+ | myCounter.click(); | ||
+ | myCounter.click(); | ||
+ | System.out.println(myCounter.count); | ||
+ | myCounter.reset(); | ||
+ | System.out.println(myCounter.count); | ||
+ | </ | ||
+ | |||
+ | ===== Where does the code go? ===== | ||
+ | |||
+ | ==== The easy-for-beginners way ==== | ||
+ | If there' | ||
+ | |||
+ | <file java ClickerCounter.java> | ||
+ | public class ClickerCounter { | ||
+ | |||
+ | // Class definition (instance members) | ||
+ | int count; | ||
+ | | ||
+ | void click(){ | ||
+ | count++; | ||
+ | } | ||
+ | | ||
+ | void reset(){ | ||
+ | count = 0; | ||
+ | } | ||
+ | |||
+ | // Program' | ||
public static void main(String[] args) { | public static void main(String[] args) { | ||
var myCounter = new ClickerCounter(); | var myCounter = new ClickerCounter(); | ||
Line 71: | Line 101: | ||
</ | </ | ||
+ | This isn't generally recommended though because very often you will write more than one custom class in your program. If this is the case, the approach above won't work because Java's rules say any file can only contain at most one public class definition.((You //can// have additional non-public class definitions in a file, but that's something we can't discuss yet.)) | ||
- | ===== Access specifiers | + | ==== The better way ==== |
- | The '' | + | |
- | <file java ClickerExample.java> | + | A better way to manage your programs' |
- | public | + | |
- | public static void main(String[] args) { | + | The following is how to break up the class definition and the "main" stuff. Here is the file that has only the class definition: |
- | var myCounter = new ClickerCounter(); | + | |
- | + | ||
- | myCounter.reset(); | + | |
- | myCounter.count = 492341; | + | |
- | System.out.println(myCounter.count); | + | |
- | myCounter.click(); | + | |
- | myCounter.click(); | + | |
- | System.out.println(myCounter.count); | + | |
- | } | + | |
- | } | + | |
- | </file> | + | |
- | the object will happily oblige the user's wish to set the count to some arbitrary value. That's not something you can typically do with a clicker counter. In other words, the object offers no **protection** of its state. This is easy enough to solve with Java's access modifiers. Let's look at a modified version of our class definition that gives us some protection using access modifiers: | + | <file java ClickerCounter.java> |
+ | public | ||
- | <file java ClickerCounter.java> | + | // Class definition |
- | public class ClickerCounter { | + | int count; |
| | ||
- | | + | void click(){ |
- | + | ||
- | public | + | |
count++; | count++; | ||
} | } | ||
| | ||
- | | + | void reset(){ |
count = 0; | count = 0; | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | Access modifiers are placed before the start of a member. Java offers four levels of protection, and they just so happen to all start with the letter ' | ||
- | * '' | ||
- | * '' | ||
- | * '' | ||
- | * '' | ||
- | |||
- | With the changes made above, if we try to run '' | ||
- | |||
- | <code java> | ||
- | myCounter.count = 492341; | ||
- | </ | ||
- | |||
- | it cannot access the '' | ||
- | |||
- | <WRAP center round tip 80%> | ||
- | In Java programming, | ||
- | |||
- | Methods can be at whatever access level is appropriate for their use. If it is part of the class' interface, it should be '' | ||
- | </ | ||
- | |||
- | |||
- | ===== Accessors and mutators ===== | ||
- | |||
- | ==== Accessors ==== | ||
- | |||
- | If we comment out the offending line above, we will see that the program //still// does not compile. The reason for this is in the statement: | ||
- | |||
- | <code java> | ||
- | System.out.println(myCounter.count); | ||
- | </ | ||
- | |||
- | The compiler is trying to access '' | ||
- | |||
- | So, once you make a member variable private or protected, how do we get its value?? The answer is you can write a public method that simply returns the value of the member variable: | ||
- | |||
- | <file java ClickerCounter.java> | ||
- | public class ClickerCounter { | ||
- | | ||
- | private int count; | ||
- | | ||
- | // NEW! accessor method | ||
- | public int getCount(){ | ||
- | return count; | ||
} | } | ||
- | | ||
- | public void click(){ | ||
- | count++; | ||
- | } | ||
- | | ||
- | public void reset(){ | ||
- | count = 0; | ||
- | } | ||
} | } | ||
</ | </ | ||
- | This is an example of an **accessor**: | + | And here is the file that has the "main" |
- | + | ||
- | We can now change our '' | + | |
- | + | ||
- | <code java> | + | |
- | public static void main(String[] args) { | + | |
- | var myCounter = new ClickerCounter(); | + | |
- | + | ||
- | myCounter.reset(); | + | |
- | System.out.println(myCounter.getCount()); | + | |
- | myCounter.click(); | + | |
- | myCounter.click(); | + | |
- | System.out.println(myCounter.getCount()); | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | and life if good. Accessors are sometimes called **getters**, | + | |
- | ==== Mutators ==== | + | |
- | + | ||
- | Let's now add a feature to our counter that lets the user set the maximum count: after the counter reaches the maximum, it should reset. Just like a physical clicker counter that only counts up to, say, 9,999. | + | |
- | + | ||
- | We'll need another member variable to store this upper bound, and we'll have to modify the '' | + | |
- | + | ||
- | <code java> | + | |
- | + | ||
- | private int maxCount; // new member variable | + | |
- | + | ||
- | ... | + | |
- | + | ||
- | // modified click() method | + | |
- | public void click(){ | + | |
- | if (count < maxCount) { | + | |
- | count++; | + | |
- | } else { | + | |
- | count = 0; | + | |
- | } | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | Following best-practices, | + | |
- | + | ||
- | <code java> | + | |
- | // NEW! mutator for maxCount | + | |
- | public void setMaxCount(int newMax) { | + | |
- | if (newMax > 0) { | + | |
- | maxCount = newMax; | + | |
- | } else { | + | |
- | System.out.println(" | + | |
- | } | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | Mutators should checks that new values are valid. This is another example of what's needed to make an object **self-governing**. | + | |
- | + | ||
- | Mutators are sometimes called **setters**, | + | |
- | + | ||
- | Putting it all together, we now have: | + | |
- | + | ||
- | <file java ClickerCounter> | + | |
- | /** | + | |
- | * Encapsulate a tally counter/ | + | |
- | */ | + | |
- | public class ClickerCounter { | + | |
- | + | ||
- | // Member variables | + | |
- | private int count; | + | |
- | private int maxCount; | + | |
- | + | ||
- | // Accessors and mutators | + | |
- | public int getCount() { | + | |
- | return count; | + | |
- | } | + | |
- | + | ||
- | public void setMaxCount(int newMax) { | + | |
- | if (newMax > 0) { | + | |
- | maxCount = newMax; | + | |
- | } else { | + | |
- | System.out.println(" | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | // Interface methods | + | |
- | public void click() { | + | |
- | if (count < maxCount) { | + | |
- | count++; | + | |
- | } else { | + | |
- | count = 0; | + | |
- | } | + | |
- | } | + | |
- | + | ||
- | public void reset() { | + | |
- | count = 0; | + | |
- | } | + | |
- | } | + | |
- | </ | + | |
<file java ClickerExample.java> | <file java ClickerExample.java> | ||
Line 263: | Line 131: | ||
public static void main(String[] args) { | public static void main(String[] args) { | ||
- | var myCounter = new ClickerCounter(); | + | var myCounter = new ClickerCounter(); |
| | ||
- | myCounter.setMaxCount(100); | ||
myCounter.reset(); | myCounter.reset(); | ||
- | | + | myCounter.click(); |
- | | + | System.out.println(myCounter.count); |
- | } | + | myCounter.click(); // count is 2 |
- | System.out.println(myCounter.getCount()); // 99 | + | myCounter.click(); |
- | myCounter.click(); | + | System.out.println(myCounter.count); |
- | System.out.println(myCounter.getCount()); // 100 | + | myCounter.reset(); // count is 0 |
- | myCounter.click(); | + | System.out.println(myCounter.count); |
- | System.out.println(myCounter.getCount()); // 0 | + | |
} | } | ||
} | } | ||
</ | </ | ||
- | <WRAP center round tip 80%> | + | This is the best way to manage your files, |
- | Many new programmers feel the need to write both accessors | + | |
- | </ | + | |
- | + | ||
- | ===== this ===== | + | |
- | + | ||
- | sajdlfjalsdf | + | |
- | + | ||
- | + | ||
- | ===== Constructors ===== | + | |
- | + | ||
- | ==== Default constructors ==== | + | |
- | Instance variables have default values. For numbers, | + | |
- | + | ||
- | Adding a constructor to our class definition that does the nefarious deed mentioned above looks like: | + | |
- | + | ||
- | ... | + | |
- | + | ||
- | Note the syntax: A constructor does not have a return type, is declared with '' | + | |
- | + | ||
- | So, in short, constructors are used to _initialize_ objects. They can be used for other purposes as well, but object initialization is the main reason they were invented. | + | |
- | + | ||
- | ==== Parameterized constructors ==== | + | |
- | + | ||
- | ===== Miscellany ===== | + | |
- | + | ||
- | ==== toString() ==== | + | |
- | + | ||
- | One thing you'll want to get into the habit of doing with your class definitions is to write a '' | + | |
- | + | ||
- | <code java> | + | |
- | public String toString() { | + | |
- | return | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | Now if we want to output the state of a counter using '' | + | |
- | + | ||
- | <code java> | + | |
- | System.out.println(myCounter); | + | |
- | </ | + | |
- | + | ||
- | Writing a '' | + | |
- | + | ||
- | ----------------------------------------------------------------------- | + | |
- | Copyright © 2011-2018 | + | Copyright © 2020 Mithat Konar. All rights reserved. |
java/defining_classes_in_java.txt · Last modified: 2020/09/14 01:38 by mithat