Skip to content

Instantly share code, notes, and snippets.

@NightlyNexus
Created April 30, 2015 06:54
Show Gist options
  • Save NightlyNexus/346474d9c48530c31d2f to your computer and use it in GitHub Desktop.
Save NightlyNexus/346474d9c48530c31d2f to your computer and use it in GitHub Desktop.
OOP Issue

Try GiveADogABone with ArrayListNaive (commented out, line 30) and ArrayListBest.

Calling non-final (or non-private) methods on an an Object’s instance from within the Class defining the Object makes the Object's functionality unpredictable.

When User B extends User A’s Class, User B should not have to know the implementation of the Class he is extending, but this example shows why he might need to know the implementation if User A had called non-final (or non-private) methods internally.

Protected final and private methods should do the implementation of functionality. Non-final methods should exist only as APIs for external use.

This also means that non-final protected methods are useless, but this will cause a conflict with the idea of an abstract class (as opposed to an interface).

import java.util.Collection;
/**
* @author Eric Cochran
*/
public class ArrayListBest<T> {
private static final int DEFAULT_CAPACITY = 10;
private final int initialCapacity;
private T[] arr;
private int index;
public ArrayListBest() {
this(DEFAULT_CAPACITY);
}
public ArrayListBest(int initialCapacity) {
this.initialCapacity = initialCapacity;
init();
}
private void init() {
arr = (T[]) new Object[initialCapacity];
index = 0;
}
public void add(T data) {
addHelper(data);
}
public void addAll(Collection<T> collection) {
for (T item : collection) {
addHelper(item);
}
}
private void addHelper(T data) {
if (data == null) {
return;
}
if (index >= arr.length) {
T[] temp = (T[]) new Object[arr.length * 2];
int i = 0;
for (T item : arr) {
temp[i] = item;
i++;
}
arr = temp;
}
arr[index] = data;
index++;
}
}
import java.util.Collection;
/**
* @author Eric Cochran
*/
public class ArrayListNaive<T> {
private static final int DEFAULT_CAPACITY = 10;
private final int initialCapacity;
private T[] arr;
private int index;
public ArrayListNaive() {
this(DEFAULT_CAPACITY);
}
public ArrayListNaive(int initialCapacity) {
this.initialCapacity = initialCapacity;
init();
}
private void init() {
arr = (T[]) new Object[initialCapacity];
index = 0;
}
public void add(T data) {
if (data == null) {
return;
}
if (index >= arr.length) {
T[] temp = (T[]) new Object[arr.length * 2];
int i = 0;
for (T item : arr) {
temp[i] = item;
i++;
}
arr = temp;
}
arr[index] = data;
index++;
}
public void addAll(Collection<T> collection) {
for (T item : collection) {
this.add(item);
}
}
}
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @author Eric Cochran
*/
public class GiveADogABone {
public static void main(String[] args) {
final int numBones = 5;
final List<Bone> bonesInHand = new ArrayList<Bone>(numBones);
final BarkerList<Bone> bonesGivenToDog = new BarkerList<Bone>(numBones);
// filling my hands with bones
for (int i = 0; i < numBones; i++) {
bonesInHand.add(new Bone());
}
// giving the bones to the dog
bonesGivenToDog.addAll(bonesInHand);
bonesInHand.clear();
// How many times does the dog thank me (by barking)?
}
private static class Bone {}
/**
* @author Eric Cochran
*/
public static class BarkerList<T>
extends /*ArrayListNaive*/ArrayListBest<T> {
public BarkerList() {
super();
}
public BarkerList(int initialCapacity) {
super(initialCapacity);
}
@Override
public void add(T obj) {
bark();
super.add(obj);
}
@Override
public void addAll(Collection<T> objCollection) {
for (int i = 0; i < objCollection.size(); i++) {
bark();
}
super.addAll(objCollection);
}
private static void bark() {
System.out.println("Bark!");
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment