black box and inheritance - java

Hello Stackoverflowers,
Imagine the following Base class
import java.util.ArrayList;
public class Array
{
private ArrayList<Object> a = new ArrayList<Object>();
public void add(Object element)
{
a.add(element);
}
public void addAll(Object elements[])
{
for (int i = 0; i < elements.length; ++i)
a.add(elements[i]); // this line is going to be changed
}
}
And here’s the Derived class:
public class ArrayCount extends Array
{
private int count = 0;
#Override
public void add(Object element)
{
super.add(element);
++count;
}
#Override
public void addAll(Object elements[])
{
super.addAll(elements);
count += elements.length;
}
}
The Array add() adds an element to a local ArrayList.
The Array addAll() calls the local ArrayList add for each element.
The ArrayCount add() calls its parent’s add() and then increments the count.
The ArrayCount addAll() calls its parent’s addAll() and then increments the count by the number of elements.
Now for the breaking change. The commented line of code in the Base class is changed to the following:
public void addAll(Object elements[])
{
for (int i = 0; i < elements.length; ++i)
add(elements[i]); // this line was changed
}
Now ArrayCount addAll() calls its parent’s addAll() which internally calls the add() which has been overriden by the Derived class.
The author of the Derived class must know how the Base class has been implemented. And they must be informed about every change in the Base class since it could break their Derived class in unpredictable ways.
I'm looking for a correct way to implement this that would respect black box programming concept. Because this exemple force the writter of the derivated class to know how the base class is implemented and know every change

I assume by "Black Box" you mean: "Implementer of the derived class must not know about the implementation details of the base class Array". I would opt for a decorator using delegation as probably being the better approach:
public class ArrayCount {
private int count = 0;
private Array a;
public ArrayCount(Array a) {
this.a = a;
}
public void add(Object element) {
a.add(element);
++count;
}
public void addAll(Object elements[]) {
a.addAll(elements);
count += elments.length;
}
}
Note: I left out input param checking for brevity.
If both Array and ArrayCount implement the same interface, e.g. IArray, you can still use the classes interchangeably:
interface IArray {
public void add(Object element);
public void addAll(Object elements[]);
}
...
Array implements IArray {...}
ArrayCount implements IArray {...}

When you use the Black box approach you just call method of an object and so you don't care about how it is implemented.
The public method of a Class is a contract that define what you provide and what you get.
The developer that maintain the Class could change anything but the contract or the method signatures.
If you extend a Class, and you're going to override a method or more methods, than you should care about the Class implementation, as you are going to specialize some behaviors of the Class.
To have a clean separation of different classes that have same interface, you should use the java interface, so each developer could do the own implementation of the business logic.
You could design a Class to be extendable from someone else, when you know that some method could be specialized.
But if you don't want that, you could decide that the method could not be overridden by defining those method final.
In this way you are telling to other developers that will use your code that you don't want to extend some behaviors.

Mark the base class methods as final but include supporting methods for extension.
import java.util.ArrayList;
public class Array {
private final ArrayList<Object> a = new ArrayList<Object>();
public final void add(Object element) {
a.add(element);
afterAdd(element);
}
public final void addAll(Object[] elements) {
for (Object element : elements) {
a.add(element);
}
afterAddAll(elements);
}
protected void afterAddAll(Object[] elements) {
return;
}
protected void afterAdd(Object element) {
return;
}
}
so a subclass can only override the support methods
public class ArrayCount extends Array {
private int count = 0;
#Override
protected void afterAdd(Object element) {
++count;
}
#Override
protected void afterAddAll(Object[] elements) {
count += elements.length;
}
}

Related

Is there a specific way to give a certain subclass some functions of the superclass?

The Problem
I'm trying to create an application where an object class can implement some
operations from the total pool of available operations. The end goal is to not have any code duplication and to abide by the laws of OOP as much as possible.
In more detail, I'm trying to make a search engine using Lucene. Lucene
uses many indices. I've already implemented a simple structure where different index-objects inherit the methods of a parent class. The problem is that, whatever method is implemented in that parent class, it automatically becomes available for all subclasses to use. I want to give the option to the user to determine if he wants to do a phrase search, a term search or whatever else there is available for that specific index. The catch is, some indices shouldn't have the option to conduct phrase search, for example.
First Thoughts
I've thought of implementing something close to the Composite pattern,
as described by the GoF. I would implement the search operations (e.g. term search, phrase search) as primitive operations implementing some Component class and add these primitive objects later on to a Composite object. The Composite object will be implementing the same Component class as the primitives.
public abstract class Index {
public Index(String indexPath) {
// Constructor using the information provided by the subclass
}
public void phraseSearch(...) {
// Do the operation
}
public void termSearch(...) {
// Do the operation
}
public void categorySearch(...) {
// Do the operation
}
}
public class ReviewIndex extends Index {
public ReviewIndex() {
super("./review_index/");
}
}
public class TipIndex extends Index {
public TipIndex() {
super("./tip_index/");
}
}
Expected Outcome
The class ReviewIndex shouldn't be able to perform a categorySearch but be
able to execute phraseSearch and termSearch. Respectively, the TipIndex class
should be able to execute some of the parent class methods.
Final Thoughts
I know that in my solution there is no code duplication but there
are useless methods being generated each time a new index object is created.
Thank you all in advance!
P.S. If you think the Composite pattern is the way to go, in which way would you actually add the primitive objects to the composite class and in which way would you invoke them when need to?
All methods defined in a superclass are available at deriving classes but with Java 8 you might be able to get something like this by using default-methods in interfaces. So instead of one abstract class containing all possible methods you might implement four interfaces
public interface Searchable {
public String getIndexPath();
}
public interface PhraseSearchable extends Searchable {
public default void phraseSearch() {
String indexPath = getIndexPath();
// do the search
}
}
public interface TermSearchable extends Searchable {
public default void termSearch() {
String indexPath = getIndexPath();
// do the search
}
}
public interface CategorySearchable extends Searchable {
public default void categorySearch() {
String indexPath = getIndexPath();
// do the search
}
}
To avoid duplicate code you can create an abstract class
public abstract class AbstractSearchable implements Searchable {
private String indexPath;
public AbstractSearchable(String indexPath) {
this.indexPath = indexPath;
}
// other methods that might be useful
}
Your actual classes can then implement the corresponding interfaces
public class ReviewIndex extends AbstractSearchable implements CategorySearchable {
public ReviewIndex() {
super("./review_index/");
}
}
public class TipIndex extends AbstractSearchable implements PhraseSearchable, TermSearchable {
public ReviewIndex() {
super("./review_index/");
}
}
If this is possible depends heavily on the actual implementation of the search methods. Interfaces can't contain any members, etc. so these methods must be able to run for themselves (like a static method without using any static members of the class). You might to overcome this problem by adding more methods to the Searchable interface that provide the data and do the implementation in the abstract class but that might expose internal stuff to the public because all the declared methods in an interface are public.
If you don't want to use categorySearch(...) for ReviewIndex class then create one more hierarchy where you keep the categorySearch(...) method.
Example:
public abstract class Index {
public Index(String indexPath) {
// Constructor using the information provided by the subclass
}
public void phraseSearch(...) {
// Do the operation
}
}
// Give a meaningful Name
public abstract class IndexChild1 extends Index {
public void categorySearch(...) {
// Do the operation
}
}
// Give a meaningful Name
public abstract class IndexChild2 extends Index {
public void termSearch(...) {
// Do the operation
}
}
public class ReviewIndex extends IndexChild1 {
public ReviewIndex() {
super("./review_index/");
}
}
public class TipIndex extends IndexChild2 {
public TipIndex() {
super("./review_index/");
}
}
You can use Composite pattern if you need to have the same objects and use them as you wish in your ReviewIndex and TipIndex classes. you can use a list which implies aggregation and you can use one instantiation of each object(PhraseSeach, TermSearch, CategorySearch) in any order you want.
here is the code:
import java.util.ArrayList;
import java.util.List;
public class Main{
public static void main(String[] args) {
Main m = new Main();
m.run();
}
public void run() {
ReviewIndex ri = new ReviewIndex();
}
public interface ISearch {
public void search();
}
public class SearchComposite implements ISearch{
private List<ISearch> l = new ArrayList<ISearch>();
public SearchComposite(String index) {
System.out.println(index);
}
public int addSearch(ISearch search) {
l.add(search);
return this.l.size() - 1;
}
public List<ISearch> getSearch(){
return this.l;
}
public void search() {
System.out.println("search");
}
}
public class CategorySearch implements ISearch{
#Override
public void search() {
System.out.println("category search");
}
}
public class PhraseSearch implements ISearch{
#Override
public void search() {
System.out.println("phrase search");
}
}
public class TermSearch implements ISearch{
#Override
public void search() {
System.out.println("term search");
}
}
CategorySearch cs = new CategorySearch();
TermSearch ts = new TermSearch();
PhraseSearch ps = new PhraseSearch();
public class ReviewIndex {
SearchComposite sc = new SearchComposite("./review_index/");
public ReviewIndex() {
int p = sc.addSearch(ps);
int t = sc.addSearch(ts);
sc.search();
List<ISearch> s = sc.getSearch();
s.get(p).search();
s.get(t).search();
}
}
public class TipIndex {
SearchComposite sc = new SearchComposite("./tip_index/");
public TipIndex() {
int p = sc.addSearch(ps);
int t = sc.addSearch(ts);
int c = sc.addSearch(cs);
sc.search();
List<ISearch> s = sc.getSearch();
s.get(p).search();
s.get(t).search();
s.get(c).search();
}
}
}
the output of the code above is:
./review_index/
search
phrase search
term search
and we have used the same CategorySearch, TermSearch and PhraseSearch for ReviewIndex and TipIndex classes.

How to shrink code with ProGuard that depends on unimplemented interface

I have a class with lots of methods. Every method performs a loop over a collection of objects and calls a certain method on that object if it implements an interface.
I am trying to make the code in such a way that proguard would remove the methods that use interfaces without any implementing class.
I have tried with using two kinds of loops over the collection, in both cases ProGuard succeeds in removing the code that uses interface without implementation, but leaves an empty loop.
Given my code:
Original code
public class EventBus {
private ArrayList<Handler> handlers = new ArrayList<Handler>();
public void notifyHappy() {
for (Handler handler: handlers) {
if (handler instanceof HandlerHappy) {
((HandlerHappy) handler).notifyHappy();
}
}
}
public void notifySad() {
final int size = handlers.size();
for (int i=0; i<size; i++) {
Handler handler = handlers.get(i);
if (handler instanceof HandlerSad) {
((HandlerSad) handler).notifySad();
}
}
}
}
Optimized code
public final class a {
private ArrayList a = new ArrayList();
public final void a() {
Iterator localIterator = this.a.iterator();
while (localIterator.hasNext())
localIterator.next();
}
public final void b() {
int i = this.a.size();
for (int j = 0; j < i; j++)
;
}
}
proguard.cfg
-assumenosideeffects class java.util.ArrayList {
public *** get(int);
public int size();
}
# disabled merging to produce clear output, doesn't affect the shrinking
-optimizations !class/merging/*,!method/inlining/*
I want proguard to remove notifyHappy method if there is no class implementing HandlerHappy interface and to remove notifySad method when no class implements HandlerSad.
Do you expect the unimplemented interface to be implemented by a party external to your package ?
If not, then why is the unimplemented interface even there ?
If yes, what is the point of anybody doing so if you let PG "optimize" away the invocations of that method ?

Tips: wrapping class in java in order to add new methods

I would like to ask you some tips about this java scenario:
I have a simple interface called Sequence that performs some basic operation. Now I would like to implement some additional methods in a separate class, called SequenceWrapper, that implements the Sequence defined above. Here is some example code that looks like my real code:
public interface Sequence {
public void methodOne();
public int methodTwo();
}
public abstract class SequenceWrapper implements Sequence {
private wrappedSequence = null;
public SequenceWrapper(Sequence sequence){
this.wrappedSequence = sequence;
}
public void methodOne(){
wrappedSequence.methodOne();
}
public int methodTwo(){
return wrappedSequence.methodTwo();
}
}
public class ConcreteWrapper extends SequenceWrapper {
public ConcreteWrapper(Sequence sequence){
super(sequence);
}
// Just an example
public int addMethodOne(){
int a = super.methodTwo();
return a + 3;
}
}
Now if I want to implements a class with another method (say 'addMethodTwo()') I can simply extends the 'ConcreteWrapper' class and add only the new method:
public class ConcreteWrapperTwo extends ConcreteWrapper {
public ConcreteWrapperTwo(Sequence sequence){
super(sequence);
}
public int addMethodTwo(){
int a = super.methodTwo();
return a + 30;
}
}
What do you think? Is this code correct or it's preferable another strategy??
Thanks in advance
First, your private wrappedSequence = null; has no type.
I suppose you meant private Sequence wrappedSequence = null;
Second, in your example you will never be able to instantiate any of the classes, since all of them receive another Sequence in the constructor and there is no way of create the first instance of Sequence.
Third, composition over inheritance is a good approach, if you really need it. Usually you wrap an object when you need to hide or protect the access to the wrapped object. In your case, within the wrapper you are exposing all of the methods of the wrapped object. You then create new methods that will affect the wrapper object, but not the wrapped one.
What you probably need is just a normal inheritance scenario:
I would like to walk you through you a breakdown for this Java scenario:
I have a simple interface called Sequence that performs some basic operation. Now I would like to implement some additional methods in a separate class, called SequenceWrapper that implements the Sequence as defined above. Here is some example code to explain what I mean:
public interface Sequence {
public void methodOne();
public int methodTwo();
}
public abstract class AbstractSequence implements Sequence {
public SequenceWrapper( ){ }
public void methodOne(){
//basic behavior here
}
public int methodTwo(){
//basic behavior here
}
}
public class ConcreteSequence extends AbstractSequence {
public ConcreteSequence ( ){
super( );
}
// Just an example
public int addMethodOne(){
int a = methodTwo();
return a + 3;
}
}
public class ConcreteSequenceTwo extends AbstractSequence {
public ConcreteSequenceTwo( ){
super( );
}
public int addMethodTwo(){
int a = methodTwo();
return a + 30;
}
}

Calling methods from objects which implement an interface

I am trying to wrap my head around interfaces, and I was hoping they were the answer to my question.
I have made plugins and mods for different games, and sometimes classes have onUpdate or onTick or other methods that are overridable.
If I make an interface with a method, and I make other classes which implement the method, and I make instances of the classes, then how can I call that method from all the objects at once?
You'll be looking at the Observer pattern or something similar. The gist of it is this: somewhere you have to keep a list (ArrayList suffices) of type "your interface". Each time a new object is created, add it to this list. Afterwards you can perform a loop on the list and call the method on every object in it.
I'll edit in a moment with a code example.
public interface IMyInterface {
void DoSomething();
}
public class MyClass : IMyInterface {
public void DoSomething() {
Console.WriteLine("I'm inside MyClass");
}
}
public class AnotherClass : IMyInterface {
public void DoSomething() {
Console.WriteLine("I'm inside AnotherClass");
}
}
public class StartUp {
private ICollection<IMyInterface> _interfaces = new Collection<IMyInterface>();
private static void Main(string[] args) {
new StartUp();
}
public StartUp() {
AddToWatchlist(new AnotherClass());
AddToWatchlist(new MyClass());
AddToWatchlist(new MyClass());
AddToWatchlist(new AnotherClass());
Notify();
Console.ReadKey();
}
private void AddToWatchlist(IMyInterface obj) {
_interfaces.Add(obj);
}
private void Notify() {
foreach (var myInterface in _interfaces) {
myInterface.DoSomething();
}
}
}
Output:
I'm inside AnotherClass
I'm inside MyClass
I'm inside MyClass
I'm inside AnotherClass
Edit: I just realized you tagged it as Java. This is written in C#, but there is no real difference other than the use of ArrayList instead of Collection.
An interface defines a service contract. In simple terms, it defines what can you do with a class.
For example, let's use a simple interface called ICount. It defines a count method, so every class implementing it will have to provide an implementation.
public interface ICount {
public int count();
}
Any class implementing ICount, should override the method and give it a behaviour:
public class Counter1 implements ICount {
//Fields, Getters, Setters
#Overide
public int count() {
//I don't wanna count, so I return 4.
return 4;
}
}
On the other hand, Counter2 has a different oppinion of what should count do:
public class Counter2 implements ICount {
int counter; //Default initialization to 0
//Fields, Getters, Setters
#Overide
public int count() {
return ++count;
}
}
Now, you have two classes implementing the same interface, so, how do you treat them equally? Simple, by using the first common class/interface they share: ICount.
ICount count1 = new Counter1();
ICount count2 = new Counter2();
List<ICount> counterList = new ArrayList<ICount>();
counterList.add(count1);
counterList.add(count2);
Or, if you want to save some lines of code:
List<ICount> counterList = new ArrayList<ICount>();
counterList.add(new Counter1());
counterList.add(new Counter2());
Now, counterList contains two objects of different type but with the same interface in common(ICounter) in a list containing objects that implement that interface. You can iterave over them and invoke the method count. Counter1 will return 0 while Counter2 will return a result based on how many times did you invoke count:
for(ICount current : counterList)
System.out.println(current.count());
You can't call a method from all the objects that happen to implement a certain interface at once. You wouldn't want that anyways. You can, however, use polymorphism to refer to all these objects by the interface name. For example, with
interface A { }
class B implements A { }
class C implements A { }
You can write
A b = new B();
A c = new C();
Interfaces don't work that way. They act like some kind of mask that several classes can use. For instance:
public interface Data {
public void doSomething();
}
public class SomeDataStructure implements Data {
public void doSomething()
{
// do something
}
}
public static void main(String[] args) {
Data mydataobject = new SomeDataStructure();
}
This uses the Data 'mask' that several classes can use and have certain functionality, but you can use different classes to actually implement that very functionality.
The crux would be to have a list that stores every time a class that implements the interface is instantiated. This list would have to be available at a level different that the interface and the class that implements it. In other words, the class that orchestrates or controls would have the list.
An interface is a contract that leaves the implementation to the classes that implements the interface. Classes implement the interface abide by that contract and implement the methods and not override them.
Taking the interface to be
public interface Model {
public void onUpdate();
public void onClick();
}
public class plugin implements Model {
#Override
public void onUpdate() {
System.out.println("Pluging updating");
}
#Override
public void onClick() {
System.out.println("Pluging doing click action");
}
}
Your controller class would be the one to instantiate and control the action
public class Controller {
public static void orchestrate(){
List<Model> modelList = new ArrayList<Model>();
Model pluginOne = new plugin();
Model plugTwo = new plugin();
modelList.add(pluginOne);
modelList.add(plugTwo);
for(Model model:modelList){
model.onUpdate();
model.onClick();
}
}
}
You can have another implementation called pluginTwo, instantiate it, add it to the list and call the methods specified by the interface on it.

Create counting class extending Hashset / Inheritance

If we consider the following class to count object added in an HashSet :
public class CountingHashSet<E> extends HashSet<E> {
public int addCount = 0;
#Override
public boolean add(E e) {
addCount +=1;
return super.add(e);
}
#Override
public boolean addAll(Collection<?
extends E> c) {
addCount += c.size();
return super.addAll(c);
}
}
Then, the JUnit test failed :
#Test
public void testCount() {
CountingHashSet<Integer> s = new CountingHashSet<>();
s.addAll(Arrays.asList(1, 2, 3, 4, 5));
for (int i = 6; i <= 10; ++i)
s.add(i);
assertEquals(10, s.addCount);
}
I get the following :
java.lang.AssertionError: expected:<10> but was <15>
Why I get 15 ? To my mind s.addAll(myCollection) call super.addAll(c) and if I look into the source code of hashSet, I saw that addAll(c) call add(e) to add each element. But why super.addAll(c) call the add method that I redefined ? (that's why I get 15 instead of 10)
You're treating inheritance as if it were composition. It's not. The calls don't end up being "add() on the HashSet" - they end up being "add() on the current object".
But why super.addAll(c) call the add method that I redefined ?
Because that's how virtual methods behave. addAll just calls add(), which will use the most overridden implementation in the actual type. That's how polymorphism always works. Let's write a simpler example:
class Superclass {
public void foo() {
bar();
}
public void bar() {
System.out.println("Superclass.bar()");
}
}
class Subclass extends Superclass {
#Override
public void bar() {
System.out.println("Subclass.bar()");
}
}
public class Test {
public static void main(String [] args) {
Superclass x = new Subclass();
x.foo(); // Prints Subclass.bar()
}
}
Is the result of Subclass.bar() what you'd expect from this example? If so, what do you expect the difference would be in your version? Just because you're calling super.addAll() doesn't mean that the object is suddenly in "non-overriding" mode or anything like that.
That's how polymorphism works. Your object is of type CountingHashSet, so a call to add will call CountingHashSet.add, even from the super type.

Categories