What is the difference between an Iterator and a Generator?
An iterator traverses a collection one at a time.
A generator generates a sequence, one item at a time.
You might for example, iterate over the result of a generator...
Generators are iterators, but not all iterators are generators.
An iterator is typically something that has a next method to get the next element from a stream. A generator is an iterator that is tied to a function.
For example a generator in python:
def genCountingNumbers():
n = 0
while True:
yield n
n = n + 1
This has the advantage that you don't need to store infinite numbers in memory to iterate over them.
You'd use this as you would any iterator:
for i in genCountingNumbers():
print i
if i > 20: break # Avoid infinite loop
You could also iterate over an array:
for i in ['a', 'b', 'c']:
print i
There's too much Python here, and too many people saying generators are the only way to implement an infinite iterator. Here's the example I mentioned (squares of all natural numbers) implemented in C#. ExplicitSquares explicitly implements an iterator (called IEnumerator in C#). ImplicitSquares uses a generator to do the same thing. Both are infinite iterators and have no backing collection. The only difference is whether the state machine is spelled out, or alternatively a generator is used.
using System.Collections;
using System.Collections.Generic;
using System;
class ExplicitSquares : IEnumerable<int>
{
private class ExplicitSquaresEnumerator : IEnumerator<int>
{
private int counter = 0;
public void Reset()
{
counter = 0;
}
public int Current { get { return counter * counter; }}
public bool MoveNext()
{
counter++;
return true;
}
object IEnumerator.Current { get { return Current; } }
public void Dispose(){}
}
public IEnumerator<int> GetEnumerator()
{
return new ExplicitSquaresEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
class ImplicitSquares : IEnumerable<int>
{
public IEnumerator<int> GetEnumerator()
{
int counter = 1;
while(true)
{
int square = counter * counter;
yield return square;
counter++;
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class AllSquares
{
private static readonly int MAX = 10;
public static void Main()
{
int i = 0;
foreach(int square in new ExplicitSquares())
{
i++;
if(i >= MAX)
break;
Console.WriteLine(square);
}
Console.WriteLine();
int j = 0;
foreach(int square in new ImplicitSquares())
{
j++;
if(j >= MAX)
break;
Console.WriteLine(square);
}
}
}
A generator is an implementation of an iterator. It is typically a routine that yields multiple values to its caller as opposed to just one.
In c#
// yield-example.cs
using System;
using System.Collections;
public class List
{
public static IEnumerable Power(int number, int exponent)
{
int counter = 0;
int result = 1;
while (counter++ < exponent)
{
result = result * number;
yield return result;
}
}
static void Main()
{
// Display powers of 2 up to the exponent 8:
foreach (int i in Power(2, 8))
{
Console.Write("{0} ", i);
}
}
}
See Wikipedia's entry
A Generator is a special function that can behave as an Iterator, returning a value each time it is called. Because it is a function, it can compute each value on demand. And because it is special, it can remember its state from the last time it was called, so the resulting code looks pretty simple.
For example, this generator in python will produce a sequence of integers
def integers():
int n = 0
while True:
yield n
n += 1
The important thing in this example is the yield n statement. The function will return the value, and the next time it is called, it will continue from that point.
This link has a longer explanation of generators in python:
link text
(from javascript useland, yet same as all others)
An interator is an object that has a .next() function
A generator is a function, once invoked, produce an iterator, it's a factory for iterator.
In javascript, generator function require a special syntax function *(){} and the use for the yield keyword
See MDN on this : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators
An iterator is used to iterate over the objects in a collection, be that an array, linked list, tree, hash map, whatever. You've got a bunch of objects and you want to do something with each one of them.
A generator doesn't just return the items from some finite collection of objects. Instead, it generates them on the fly. You could conceptualize it as an iterator over a collection that is created while you are iterating over it and may not have finite size.
For instance, you could have a generator that spits out prime numbers from 2 to infinity. There's no way you could have a collection of "all prime numbers" and iterate over it with an iterator. You need a generator.
Or you could have a generator that takes an integer and yields the factors of that number one at a time. A generator would benefit you here as you could examine the factors one by one without allocating memory for all of the factors upfront. It would also allow you to use them as they are generated rather than having to generate the entire list up front, which might be slower than you like. Here's an example of such a generator in Python:
def factors(n):
for i in xrange(1, n+1):
if n % i == 0:
yield i
for n in factors(1234567890):
print n
If you run this you can see the factors printed as they are calculated. We don't need to actually maintain an entire list of all factors in memory.
Usually iterators walk over an existing sequence (such as an array or list) and generators calculate a new value upon every request.
An iterator is commonly used to move through a collection of items. Often having MoveNext() and Current() methods. MoveNext() would shift the pointer to the next collection item (if possible) and return true/false based on success. Current() would provide the actual value.
A generator is an implementation of iterator, but instead of pointing to a pre-existing collection, it creates new items on each MoveNext() call.
Easy to understand definitions are:
Iterator is an object iterating a list of items.
Generator is a function generating an iterator.
Generator iterator is an iterator generated by generator.
Popular yet confusing definitions are:
Iterator is an object iterating a list of items.
Generator function is a function generating an iterator.
Generator is an iterator generated by generator function.
Related
I'm currently going through the paper Extensibility for the Masses. Practical Extensibility with Object Algebras by Bruno C. d. S. Oliveira and William R. Cook (available many places on the internet - for example here: https://www.cs.utexas.edu/~wcook/Drafts/2012/ecoop2012.pdf).
On page 10, they write:
Adding new data variants is easy. The first step is to create new classes Bool
and Iff in the usual object-oriented style (like Lit and Add):
class Bool implements Exp {...}
class Iff implements Exp {...}
The implementation of Exp is, it seems, left as an exercise to the reader. It's not clear to me, however, how Exp is defined in this part of the paper. My question is:
How should Bool and Iff be implemented?
Here's what I've tried:
First defintion of Exp
Early in the paper, the Exp interface is defined like this:
interface Exp {
Value eval();
}
Here, Value is defined by another interface:
interface Value {
Integer getInt();
Boolean getBool();
}
The paper, however, quickly departs from this definition of Exp in favour of a Visitor-based definition.
Possible implementation of Bool
Based on that definition, how should one implement the Bool class?
Something like this seems like a start:
class Bool implements Exp {
boolean x;
public Bool(boolean x) { this.x = x; }
public Value eval() {
return new VBool(x);
}}
The question, however, becomes how to properly implement Value?
The paper only shows this:
class VBool implements Value {...}
The implementation doesn't seem total to me:
class VBool implements Value {
boolean x;
public VBool(boolean x) { this.x = x; }
public Boolean getBool() {
return new Boolean(x);
}
public Integer getInt() {
// What to return here?
}
}
As my above attempt shows, it's not clear what to return from getInt. I suppose I could return null or throw an exception, but that would imply that my implementation is partial.
In any case, this first definition of Exp seems only to exist as a motivating example in the paper, which then proceeds to define a better alternative.
Second definition of Exp
On page 4 the paper redefines Exp as an Internal Visitor:
interface Exp {
<A> A accept(IntAlg<A> vis);
}
Where IntAlg<A> is another interface:
interface IntAlg<A> {
A lit(int x);
A add(A e1, A e2);
}
So far things seem clear, until we get to implementing Bool and Iff...
Possible implementation of Bool
How should we implement the proposed Bool class based on this definition of Exp?
class Bool implements Exp {
boolean x;
public Bool(boolean x) { this.x = x; }
public <A> A accept(IntAlg<A> vis) {
// What to return here?
}}
There's no way to conjure an A value out of thin air, so one has to interact with vis in order to produce an A value. The vis parameter, however, only defines lit and add methods.
The lit method requires an int, which isn't available in Bool.
Likewise, add requires two A values, which are also unavailable. Again, I find myself at an impasse.
Third definition of Exp?
Then, on page 8, the paper shows this example:
int x = exp(base).eval();
Here, exp(base) returns Exp, but which definition of eval is this?
Apparently, Exp still (or again?) has an eval method, but now it returns int. Does it look like this?
interface Exp {
int eval();
}
The paper doesn't show this definition, so I may be misunderstanding something.
Possible implementation of Bool
Can we implement Bool and Iff with this definition of Exp?
class Bool implements Exp {
boolean x;
public Bool(boolean x) { this.x = x; }
public int eval() {
// What to return here?
}}
Again, it's not clear how to implement the interface. One could, of course, return 0 for false and 1 for true, but that's just an arbitrary decision. That doesn't seem appropriate.
Is there a fourth definition of Exp that I'm missing? Or is there some other information in the paper that's eluding me?
BTW, I apologise if I've made mistakes in my attempts. I don't normally write Java code.
#Mark. Let me try to clarify the confusion points that you have.
Definition of Exp
The definition of Exp that we are assumming in page 10 is:
interface Exp {
Value eval();
}
which is presented earlier in the paper in Figure 1. The alternative version of Exp with visitors can be ignored. We used it merely to talk about visitors and the relationship with Object Algebras, and it does not play a role in later parts of the paper.
Also, regarding the code in page 8, I think there is a typo in the paper. You are right: it seems that there we were assuming an eval method that returns int. When we were writing the paper we were using multiple versions of Exp, and probably we used the code for another version there by mistake. The code in page 8, adapted to the representation in the paper, should be:
int x = exp(base).eval().getInt();
The Choices for Value
The code that we intended to have for the implementation of the Value class uses exceptions, similarly to your own attempt, and it is indeed partial as presented in the paper. In the paper, the point that we were making is about the extensibility and type-safety with respect to the source expressions. For the values, all we wanted was that values were rich enough to support the source expressions, and the assumption was that the values themselves were not extensible (later in Section 7 we briefly discuss extensible values). The representation that we choose in the paper was aimed at keeping the code simple, and avoid some distractions with dealing with error management (which are orthogonal to extensibility).
Agreeably this is not a great representation but, at least with the Java version at the time, it seemed like a reasonable compromise. In modern Java, I think the way to go would be to have Value modelled as an algebraic datatype. Java 16 supports pattern matching and sealed types, which can be used to essentially model algebraic datatypes in functional programming. So you could model Value with something like:
sealed interface Value {}
record VInt(int x) implements Value {}
record VBool(boolean b) implements Value {}
In retrospect, to avoid confusions like the one you're having, I think it would have been better to have presented the paper simply using the interface:
interface Exp {
int eval();
}
and to use an if construct à la C, where integers play the role of booleans. This would have avoided distractions with the representation of Value in the first place.
The Representation of Values in the Paper
In any case, getting back to the representation of the paper, and also to your point about partiality, I show a minimal, but complete implementation of the code next. For illustrating that partiality is not a fundamental issue, I also switch from using unchecked exceptions to checked exceptions.
First we can define values as follows:
interface Value {
// You can choose checked exceptions or unchecked exceptions.
// In the paper we opted for unchecked exceptions.
// But here, I show that you can also use checked exceptions,
// if you want to ensure that you deal with exception cases.
int intValue() throws Exception;
boolean boolValue() throws Exception;
}
class VInt implements Value {
int x;
public VInt(int x) {
this.x = x;
}
public int intValue() throws Exception {
return x;
}
public boolean boolValue() throws Exception {
throw new Exception();
}
public String toString() {
return Integer.valueOf(x).toString();
}
}
class VBool implements Value {
boolean b;
public VBool(boolean b) {
this.b = b;
}
public int intValue() throws Exception {
throw new Exception();
}
public boolean boolValue() throws Exception {
return b;
}
public String toString() {
return Boolean.valueOf(b).toString();
}
}
Then you can write the code with for Object Algebras as follows:
// Integer Expressions
interface IntAlg<Exp> {
Exp lit(int x);
Exp add(Exp e1, Exp e2);
}
interface Exp {
Value eval() throws Exception;
}
class IntEval implements IntAlg<Exp> {
public Exp lit(int x) {
return () -> new VInt(x);
}
public Exp add(Exp e1, Exp e2) {
return () -> new VInt(e1.eval().intValue() + e2.eval().intValue());
}
}
// Boolean Expressions
interface BoolAlg<Exp> extends IntAlg<Exp> {
Exp bool(boolean b);
Exp iff(Exp e1, Exp e2, Exp e3);
}
class BoolEval extends IntEval implements BoolAlg<Exp> {
public Exp bool(boolean b) {
return () -> new VBool(b);
}
public Exp iff(Exp e1, Exp e2, Exp e3) {
return () -> e1.eval().boolValue() ? e2.eval() : e3.eval();
}
}
public class Main {
public static <Exp> Exp m(IntAlg<Exp> alg) {
return alg.add(alg.lit(4),alg.lit(3));
}
public static <Exp> Exp m2(BoolAlg<Exp> alg) {
return alg.iff(alg.bool(false),m(alg),alg.bool(true));
}
public static void main(String[] args) {
Exp e = m(new IntEval());
try {
System.out.println(e.eval());
} catch (Exception exp) {
System.out.println("Ops! There is an error...");
}
Exp e2 = m2(new BoolEval());
try {
System.out.println(e2.eval());
} catch (Exception exp) {
System.out.println("Ops! There is an error...");
}
}
}
As you can see in the definition of the main, we need to eventually deal with the exceptions. As a matter of fact, if you wanted to deal more nicely with errors, you should change the code in the interpreter to catch the exceptions there, and then give error messages like "You cannot add a boolean to an integer..." and so on. That does involve extra code (which is not so related to the main point of the technique), but it can be easily done.
Also note that I'm using lambdas to avoid some boilerplate with anonymous classes. In Java anonymous classes with a single method implementation can be written as a lambda.
If you do not like code using exceptions, and you'd prefer a more functional-style approach, you could also use Java's Optional class to model failure (just as you'd do in a functional language like Haskell, say). In such case, you could have the following:
// Values
interface Value {
Optional<Integer> intValue();
Optional<Boolean> boolValue();
}
// The expression interface
interface Exp {
Optional<Value> eval();
}
Where we now use Optional instead of making the operations partial. The Java code (without pattern matching) with this option will not be so nice, but maybe with the new pattern matching features it won't be that bad.
I am new to oop.so i am just experimenting some stuffs.The below problem is just a made up problem but it would help me to understand oop more clearly.
I am coding to make a calculator which can only add and multiply deciaml number and binary number.
So I have an abstract class named Calculator and two child classes- binaryCalculator and decimalCalculator
There are two abstract function in my Calculator class- add(), multiply()
Now the problem is, only decimal add() function does add three numbers altogether,the rest perform only on two numbers .
So now I am kinda confused,should i make two constructor in deciamCalculator class or should i just create 4 individual child classes - drciamAddingCalculator, decimalMultiplyingCalculator, binaryAddingCalculator and
binaryMultiplyingCalculator
I'm also not understanding why the decimal calculator would need 3 numbers, but one possible approach is to have the add() and multiply() take an arbitrary amount of numbers and add/multiply them all together.
Javacript example:
class DecimalCalulator extends AbstractCalculator {
add(...numbers: number[]): number {
return numbers.reduce((sum, n) => sum + n);
}
multiply(...numbers: number[]): number {
return numbers.reduce((product, n) => product * n);
}
}
Note that these methods can be static, so already we start to question why this is a class an what an instance of this class represents.
If the instance has stored the previous number as a property, then add() and multiply() should take only one number and be void methods which modify the stored value.
class AbstractCalculator {
protected total: number = 0;
/*... */
}
class DecimalCalulator extends AbstractCalculator {
add(number: number): void {
this.total += number;
}
multiply(number: number): void {
this.total *= number;
}
}
There are a lot of ways to think about this beyond just classical inheritance. You don't need to use inheritance at all if you don't want to.
Perhaps one of BinaryOperations and DecimalOperations is passed into the constructor of a Calculator and stored as an instance variable this.operations.
Now the single responsibility of the Calculator class is to store a rolling total and update it when operations are called. It can have methods like clear() and undo(). It doesn't know about the actual math because it delegates that to this.operations.add(). Note that the Operations interface is essentially static here, so there's room to rethink this further.
interface Operations {
add(...numbers: number[]): number;
multiply(...numbers: number[]): number;
}
class Calculator {
private total: number;
private readonly operations: Operations;
constructor( operations: Operations ) {
this.total = 0;
this.operations = operations;
}
clear(): void {
this.total = 0;
}
add( number: number ): void {
this.total = this.operations.add(this.total, number);
}
multiply( number: number ): void {
this.total = this.operations.multiply(this.total, number);
}
}
If this is an interactive calculator, think about what order the actions are called in. You're not just calling an add method with a number, right? You would press the add button first, then enter the number (one digit at a time), and then press the equals button. No math is done until equals is pressed, and the calculator needs to store knowledge of which number and which operation were pressed.
So in that case instead of passing in an Operations object with methods for each operation, perhaps we pass in an array of Operation handlers, where an operation has a key or a symbol (which we use when storing the last button pressed) and a callback to call when the time is right.
interface ButtonHandler {
symbol: string;
callback( previousValue: number, enteredValue: number ): number;
}
const DecimalAdd: ButtonHandler = {
symbol: '+',
callback: ( a, b ) => a + b,
} // this is a plain javascript object, not a class, but it implements out interface
I could go on, but that should be enough food for thought.
I have a struct and I would like it to be initialised with some sensible default values.
Typically, the thing to do here is to use a constructor but since go isn't really OOP in the traditional sense these aren't true objects and it has no constructors.
I have noticed the init method but that is at the package level. Is there something else similar that can be used at the struct level?
If not what is the accepted best practice for this type of thing in Go?
There are some equivalents of constructors for when the zero values can't make sensible default values or for when some parameter is necessary for the struct initialization.
Supposing you have a struct like this :
type Thing struct {
Name string
Num int
}
then, if the zero values aren't fitting, you would typically construct an instance with a NewThing function returning a pointer :
func NewThing(someParameter string) *Thing {
p := new(Thing)
p.Name = someParameter
p.Num = 33 // <- a very sensible default value
return p
}
When your struct is simple enough, you can use this condensed construct :
func NewThing(someParameter string) *Thing {
return &Thing{someParameter, 33}
}
If you don't want to return a pointer, then a practice is to call the function makeThing instead of NewThing :
func makeThing(name string) Thing {
return Thing{name, 33}
}
Reference : Allocation with new in Effective Go.
There are actually two accepted best practices:
Make the zero value of your struct a sensible default. (While this looks strange to most people coming from "traditional" oop it often works and is really convenient).
Provide a function func New() YourTyp or if you have several such types in your package functions func NewYourType1() YourType1 and so on.
Document if a zero value of your type is usable or not (in which case it has to be set up by one of the New... functions. (For the "traditionalist" oops: Someone who does not read the documentation won't be able to use your types properly, even if he cannot create objects in undefined states.)
Go has objects. Objects can have constructors (although not automatic constructors). And finally, Go is an OOP language (data types have methods attached, but admittedly there are endless definitions of what OOP is.)
Nevertheless, the accepted best practice is to write zero or more constructors for your types.
As #dystroy posted his answer before I finished this answer, let me just add an alternative version of his example constructor, which I would probably write instead as:
func NewThing(someParameter string) *Thing {
return &Thing{someParameter, 33} // <- 33: a very sensible default value
}
The reason I want to show you this version is that pretty often "inline" literals can be used instead of a "constructor" call.
a := NewThing("foo")
b := &Thing{"foo", 33}
Now *a == *b.
There are no default constructors in Go, but you can declare methods for any type. You could make it a habit to declare a method called "Init". Not sure if how this relates to best practices, but it helps keep names short without loosing clarity.
package main
import "fmt"
type Thing struct {
Name string
Num int
}
func (t *Thing) Init(name string, num int) {
t.Name = name
t.Num = num
}
func main() {
t := new(Thing)
t.Init("Hello", 5)
fmt.Printf("%s: %d\n", t.Name, t.Num)
}
The result is:
Hello: 5
I like the explanation from this blog post:
The function New is a Go convention for packages that create a core type or different types for use by the application developer. Look at how New is defined and implemented in log.go, bufio.go and cypto.go:
log.go
// New creates a new Logger. The out variable sets the
// destination to which log data will be written.
// The prefix appears at the beginning of each generated log line.
// The flag argument defines the logging properties.
func New(out io.Writer, prefix string, flag int) * Logger {
return &Logger{out: out, prefix: prefix, flag: flag}
}
bufio.go
// NewReader returns a new Reader whose buffer has the default size.
func NewReader(rd io.Reader) * Reader {
return NewReaderSize(rd, defaultBufSize)
}
crypto.go
// New returns a new hash.Hash calculating the given hash function. New panics
// if the hash function is not linked into the binary.
func (h Hash) New() hash.Hash {
if h > 0 && h < maxHash {
f := hashes[h]
if f != nil {
return f()
}
}
panic("crypto: requested hash function is unavailable")
}
Since each package acts as a namespace, every package can have their own version of New. In bufio.go multiple types can be created, so there is no standalone New function. Here you will find functions like NewReader and NewWriter.
In Go, a constructor can be implemented using a function that returns a pointer to a modified structure.
type Colors struct {
R byte
G byte
B byte
}
// Constructor
func NewColors (r, g, b byte) *Colors {
return &Color{R:r, G:g, B:b}
}
For weak dependencies and better abstraction, the constructor does not return a pointer to a structure, but an interface that this structure implements.
type Painter interface {
paintMethod1() byte
paintMethod2(byte) byte
}
type Colors struct {
R byte
G byte
B byte
}
// Constructor return intreface
func NewColors(r, g, b byte) Painter {
return &Color{R: r, G: g, B: b}
}
func (c *Colors) paintMethod1() byte {
return c.R
}
func (c *Colors) paintMethod2(b byte) byte {
return c.B = b
}
another way is;
package person
type Person struct {
Name string
Old int
}
func New(name string, old int) *Person {
// set only specific field value with field key
return &Person{
Name: name,
}
}
If you want to force the factory function usage, name your struct (your class) with the first character in lowercase. Then, it won't be possible to instantiate directly the struct, the factory method will be required.
This visibility based on first character lower/upper case work also for struct field and for the function/method. If you don't want to allow external access, use lower case.
Golang is not OOP language in its official documents.
All fields of Golang struct has a determined value(not like c/c++), so constructor function is not so necessary as cpp.
If you need assign some fields some special values, use factory functions.
Golang's community suggest New.. pattern names.
I am new to go. I have a pattern taken from other languages, that have constructors. And will work in go.
Create an init method.
Make the init method an (object) once routine. It only runs the first time it is called (per object).
func (d *my_struct) Init (){
//once
if !d.is_inited {
d.is_inited = true
d.value1 = 7
d.value2 = 6
}
}
Call init at the top of every method of this class.
This pattern is also useful, when you need late initialisation (constructor is too early).
Advantages: it hides all the complexity in the class, clients don't need to do anything.
Disadvantages: you must remember to call Init at the top of every method of the class.
I was wondering if which of the following patterns are considered to be more "correct".
The first example sets the value of private data member length by calling a void member function that implicitly takes arguments.
The second example sets the value of length by assigning it to the return value of the member function that explicitly takes an argument.
It seems that the second method makes the code clearer, since you know when and how the private member is getting set,
where the first requires a trace of the code to verify what and how a value is being assigned. The second method
also seems like it would allow for better reuse down the road because it could operate in any class/context (since the
arguments and return type are explicit).
The first method is quicker, and if used throughout the entire class (for private member functions) can save some coding, however I'm
not sure if this will bite me down the road ?
Thank you for the insight and clearing this up for me.
class MyDataType
{
private int length;
private string content;
private char[] buffer;
public MyDataType(str)
{
content = str;
calculateLength();
buffer = new char[length+1];
for(int i=0; i < length; i++)
buffer[i] = content[i];
buffer[i] = NULL;
}
private void calculateLength()
{
int i = 0;
while(content[i++] != NULL) {} // i know, buffer overflow...
length = i;
}
}
class MyDataType
{
private int length;
private string content;
private char[] buffer;
public MyDataType(str)
{
content = str;
length = calculateLength(content);
buffer = new char[length+1];
for(int i=0; i < length; i++)
buffer[i] = content[i];
buffer[i] = NULL;
}
private int calculateLength(string s)
{
int i = 0;
while(s[i++] != NULL) {}
return i;
}
}
In terms of readability and flexibility the second example wins out.
The advantage to using the second example is that you are essentially just delegating some work in the constructor to a method. This is easy to read and won't easily break in the future if, for instance, someone calls the private calculateLength() method without expecting the instance variables to change.
In the first example the calculateLength() method is operating on the member variables in a non-transparent way to the constructor which makes it less readable and more prone to be brittle in the way described above.
I would say the second is more appropriate, but the first works.
Usually getters are public, anywhere within a class you can access a private variable, doesn't make sense to have a getter that gets a private or protected variable in the same class. If it were protected and you could pass functionality to subclasses of your class.
It depends on what you want to do with the variable. If the value isn't going to change, I would just move the private calculateLength() method to the constructor. If you have to recalculate it then I guess I can see either the void or private doing pretty much the same thing. I feel that the second is clearer because you know exactly where the calculateLength() method is returning, but in the first it it is ambiguous to whether it is doing anything at all. It's better style to do the second.
Why not embed the getLength() function content into the constructor, and do the copying simultaneously? You will save yourself another loop.
Other than that, I am pretty sure it does not matter much. Just go with the flow, start with a method, and then modify in the future if you see fit.
I have been searching for short and good examples to demonstrate OO features of a language as an introduction to fellow programmers. By "good", I mean, they can be run and output something rather meaningful not foobar stuff.
For instance, you can demonstrate most control flow constructs by a mandelbrot set example or functional aspects by a mergesort example. But I have yet to find a good example for OO constructs.
One "real world" example that's pretty straightforward to understand is the java.io.InputStream class and it's children. This is a decent example of polymorphism: if you write your code to understand how to use InputStream, it doesn't matter how the underlying class works, as long as it conforms to the contract imposed by InputStream. So, you can have a method in some class
public void dump(InputStream in) throws IOException {
int b;
while((b = in.read()) >= 0) {
System.out.println(b);
}
}
This method doesn't care where the data comes from.
Now, if you want to use the dump method with data from a file, you can call
dump(new FileInputStream("file"));
or, if you want to use dump with data from a socket,
dump(socket.getInputStream());
or, if you have a byte array, you can call
dump(new ByteArrayInputStream(theArray));
There are implementations if InputStream that wrap other InputStreams. For example, SequenceInputStream lets you glom multiple InputStreams into one:
dump(new SequenceInputStream(new FileInputStream("file1"),
new FileInputStream("file2"));
If you want to create your own, custom InputStream, you can extend the InputStream class, and override the int read() method:
public class ZerosInputStream extends InputStream {
protected int howManyZeros;
protected int index = 0;
public ZerosInputStream(int howManyZeros) {
this.howManyZeros = howManyZeros;
}
#Override
public int read() throws IOException {
if(index < howManyZeros) {
index++;
return 0;
} else {
return -1;
}
}
Then you can use that in your dump call:
dump(new ZerosInputStream(500));