In Java, is it possible to override member data in a subclass and have that overridden version be the data used in a super class's implementation?
In other words, here's what I am trying to get to happen, and it's not happening:
abstract public class BasicStuff {
protected String[] stuff = { "Pizza", "Shoes" };
public void readStuff() {
for(String p : stuff) {
system.out.println(p);
}
}
}
..
public class HardStuff extends BasicStuff {
protected String[] stuff = { "Harmonica", "Saxophone", "Particle Accelerator" };
}
This invocation:
HardStuff sf = new HardStuff();
sf.readStuff();
... prints Pizza and Shoes. I want it to print the latter instead.
I recognise that this is rather poor hierarchical OO practice; I needed it for a very specific case as I am doing something with XML configuration and reflection.
Is there a modifier that can make this happen?
And yes, I do recognise that there are wrappers one can use to get around this problem in my subclass, i.e. by indicating that the contents of stuff[] are now stored in an array with a different name, for instance. I'm just trying to keep this simple, and am curious in principle.
Thanks a lot in advance!
I believe you must interpose an accessor method, i.e., use:
for(String p : getStuff()) {
in the superclass, and add:
protected String[] getStuff() { return stuff; }
wherever you have a protected String[] stuff redefinition.
Overriding really applies to methods, not data (at least, that is so in the Java model; some other languages do things differently), and so to get the override effect you must interpose a method (typically a dirt-simple accessor, like here). It doesn't really complicate things at all, it's just a very simple way to instruct the Java compiler to use, intrinsically, the "extra level of indirection" that your desired behavior requires.
This way you are hiding the parent variable stuff with the defined stuff.
Try giving value to stuff in the initialization block (or in the constructor):
abstract public class BasicStuff {
protected String[] stuff;
{
stuff = new String[] { "Pizza", "Shoes" };
}
public void readStuff() {
for(String p : stuff) {
System.out.println(p);
}
}
}
..
public class HardStuff extends BasicStuff {
{
stuff = new String[] { "Harmonica", "Saxophone", "Particle Accelerator" };
}
}
If you want to print the array of the String Stuff defined in derived class then you need to override the method readStuff in the class HardStuff by redefining the method in the class HardStuff. As the method readStuff was defined in the abstract class BasicStuff, hence it would only print the members of the class BasicStuff. Hence, add the same method in the derieved class too.
Below you can find the complete code..
class BasicStuff {
protected String[] stuff = { "Pizza", "Shoes" };
public void readStuff() {
for(String p : stuff) {
System.out.println(p);
}
}
}
public class HardStuff extends BasicStuff {
protected String[] stuff =
{ "Harmonica",
"Saxophone",
"Particle Accelerator"
};
public void readStuff() {
for(String p : stuff) {
System.out.println(p);
}
}
public static void main(String []arg)
{
HardStuff sf = new HardStuff();
sf.readStuff();
}
}
Related
I'm trying to apply the decorator pattern to making an object that encrypts a word into a certain encryption, like the L337 method, which replaces letters like 9 with g, or 4 with r. Basically, I want to type a word into an inputfield and show the encrypted word in a text object. But I can't get the L337 decorator to inherit from the main decorator class. It won't accept the keyword 'super', so I tried the base word, but then when I implement Encrypt, it won't take the object newEncryption. Could someone help me figure out how to put this pattern together please?
I basically know what the decorator pattern is. It's making an object, making a basic decorator, and making a specific decorator, and instantiating the object with the decorating for exclusive methods and features.
public class Encryption : MonoBehaviour
{
public static InputField inputBox;
public static Text outputText;
public interface IEncryption { void Encrypt(); }
public class TextEncryption : IEncryption
{
public void Encrypt()
{
string currentText = inputBox.text;
outputText.text = currentText;
}
}
public abstract class encryptionDecorator : IEncryption
{
protected IEncryption tempEncryption;
public encryptionDecorator(IEncryption newEncryption)
{
tempEncryption = newEncryption;
}
public void Encrypt()
{
tempEncryption.Encrypt();
}
}
public class L337EncryptionDecorator : encryptionDecorator
{
public L337EncryptionDecorator(IEncryption newEncryption) : base(newEncryption)
{
print("Encrypting L337 Code");
}
public void Encrypt()
{
}
}
}
I think you actually want to use tempEncryption, but you didnt really tell where you could not use newEncryption so im guessing.
But anyway, I hope this will clear some things up. Its slightly edited from your code so I didnt need to put GUI stuff, but you could just CnP it to unity.
using UnityEngine;
public class Encryption : MonoBehaviour {
public interface IEncryption {
void Encrypt();
}
public class TextEncryption : IEncryption {
public void Encrypt() {
}
}
public abstract class EncryptionDecorator : IEncryption {
protected IEncryption tempEncryption;
public EncryptionDecorator(IEncryption newEncryption) {
//this will be called when you override the constructor
Debug.Log("In EncryptionDecorator constructor: " + newEncryption.GetType());
tempEncryption = newEncryption;
}
//if you are going to override a method in a child class,
//declare it either abstract ("no body; passes implementation to child") or
//virtual ("allows for a base implementation")
public virtual void Encrypt() {
Debug.Log("In EncryptionDecorator.Encrypt(): " + tempEncryption.GetType());
tempEncryption.Encrypt();
}
}
public class L337EncryptionDecorator : EncryptionDecorator {
public L337EncryptionDecorator(IEncryption newEncryption) : base(newEncryption) {
//newEncryption is a parameter, think of it as sort of a local variable.
//but since you pass it down to the parent class, it gets assigned to tempEncryption
//the base-class constructor is called first!
Debug.Log("In L337EncryptionDecorator constructor: " + newEncryption.GetType());
}
//this overrides the base implementation. you can call it with
//base.Encrypt() though.
public override void Encrypt() {
//you have no parameters here, but you could use the inherited variable tempEncryption because you declared it protected
Debug.Log("In L337EncrytionDecorator.Encrypt(): " + tempEncryption.GetType());
//base refers to the base class
base.Encrypt();
}
}
void Start() {
IEncryption encryption = new L337EncryptionDecorator(new TextEncryption());
encryption.Encrypt();
}
}
or maybe i missed what this is all about?!
There is a given method. How can we refactor it?
public void foo(Factor o){
if(o.matches(constant1)){
method1();
}else if(o.matches(constant2)){
method2();
}
}else if(o.matches(constant3)){
method3();
}
....
}
This is something called a code smell. You would want to use what's called the "command pattern" which is a design pattern to refactor this code. On mobile now, will update with an example when I get to my desk today.
Edit: Here we go.
So the command pattern is a design pattern used for this exact scenario. What you need to first do is create a command Interface.
public interface MyCommand {
public void execute();
}
Great. Next you create Command objects that hold all of your method data.
public class Method1Command implements MyCommand {
public MyVariable var;
public Method1Command(<your arguments to create method>)
{
// instantiate your command
}
public void execute()
{
// what your current method1() is;
}
}
And then you just create some kind of private class in your Main to create a HashMap of all of the commands, keyed with the value of "ConstantX."
private static Map<String, MyCommand> getMyCommands()
{
Map<String, MyCommand> commandList = new HashMap<String, MyCommand>();
MyCommand c;
c = new Method1Command();
commandList.put("constant1", c);
c = new Method2Command();
commandList.put("constant2", c);
c = new Method3Command();
commandList.put("constant3", c);
return commandList();
}
Then, in the refactored method you would simply do the following:
public void foo(Factor o)
{
cl.get(o).execute();
}
This, however, assumes that o has some kind of toString method inside it, or if you have some method inside of o that you use to get the command it would be something like this: cl.get(o.getMyCommand()).execute();
You can make an array containing the constants, and a Map containing constant-string pairs (String is the name of the method), use reflection and do something like:
public void foo(Factor o) {
for(int i = 0; i < constans.length; i++) {
if(o.matches(constant)) {
Method method =
YourClass.class.getMethod(myMap.get(constant), null);
method.invoke(null);
}
}
}
I am working on a project in java and am quite new to the language and OOP. My dilema is that I want to carry out a task/function from a specific class based on the value of a variable.
This is kind of what I am trying to achieve.
class mainClass{
String option;
public static void main(String[] args) {
mainClass main = new mainClass();
}
mainClass(){
secondClass sC = new secondClass();
thirdClass tC = new thirdClass();
switch (option){
case "1" :
sC.doSomething();
case "2" :
tC.doSomething();
}
}
}
class secondClass{
void doSomething(){
System.out.println("1");
}
}
class thirdClass{
void doSomething(){
System.out.println("2");
}
}
The reason I don't want to do this, is because if I want to add a fourth, fifth, sixth class etc... I would have to update the switch.
I tried using a hashmap. Where I assigned secondClass the key of "1". But then I would have to cast the object, but this brings me back to the original headache of not knowing what class would need to be called in advance.
So then I tried using a hashmap like this,
HashMap<String, Object> map = new HashMap<String, Object>();
Which I could then do map.get("1") but then now I can't call any of the methods for the class in question.
If I need to use a large switch statement I will, but I am actively seeking a more efficient alternative.
You were right to use a Map but you were also right to balk at casting. However, nowadays with generics you can get around all that:
interface DoesSomething {
// An object implementing this interface does something.
public void doSomething();
}
// Class that does something.
class FirstClass implements DoesSomething {
#Override
public void doSomething() {
// What FirstClass does.
}
}
// Another class that does something.
class SecondClass implements DoesSomething {
#Override
public void doSomething() {
// What SecondClass does.
}
}
// How I know what to do. Map the string to a DoesSomethng.
Map<String, DoesSomething> whatToDo = new HashMap<>();
{
// Populate my map.
whatToDo.put("1", new FirstClass());
whatToDo.put("2", new SecondClass());
}
public void doSomethingDependingOnSomething(String something) {
// Look up the string in the map.
DoesSomething toDo = whatToDo.get(something);
// Was it in there?
if (toDo != null) {
// Yes! Make it do it's thing.
toDo.doSomething();
}
}
If you want to avoid using Reflection (wich is discouraged here), you should consider a simple SAM-Interface:
public interface Doable { public void doSomething(); }
and have all classes implement the interface (no other changes required in these classes) and having a Map<String, Doable> and calling
if (map.containsKey(option)) map.get(option).doSomething();
// Or (may be a little faster)
Doable opt = map.get(option);
if (opt != null) opt.doSomething();
If your implementations have different methods, you'll most likely be bound to use Reflection to get the declared methods and compare by String.
I want a hard reference class in my Java code, but, of course, there isn't one. Is there some other way to do what I want, or should I make my own class?
This comes up with anonymous classes in methods where I want the anonymous class to set the return value for the method.
For example, given
interface Greeting {
void greet();
}
I want code like the following:
// Does not compile
static void hello(final String who) {
String returnValue;
Greeting hello = new Greeting() {
public void greet() {
returnValue = "hello" + who;
}
};
hello.greet();
System.out.println(returnValue);
}
I can fake it using a list:
static void hello(final String who) {
final List<String> returnValue = new ArrayList<String>();
Greeting hello = new Greeting() {
public void greet() {
returnValue.add("hello" + who);
}
};
hello.greet();
System.out.println(returnValue.iterator().next());
}
But I want to not use a list. I can write a StrongReference class that solves this:
static class StrongReference<T> {
private T referent;
public void set(T referent) {
this.referent = referent;
}
public T get() {
return referent;
}
}
which makes my method clearer:
static void hello(final String who) {
final StrongReference<String> returnValue = new StrongReference<String>();
Greeting hello = new Greeting() {
public void greet() {
returnValue.set("hello" + who);
}
};
hello.greet();
System.out.println(returnValue.get());
}
For my contrived example, I could have greet() return a String, but I'm working with much more complex classes, where the setting is deep within a database call that the base class manages. The instances have many different types they want to return, so I've just been using the List trick.
My questions are: Is there a better way to do this? What's wrong with my StrongReference class? Has anyone written a StrongReference in a library somewhere?
If you want something from the standard API, perhaps an AtomicReference would do?
It has void set(V value) and a V get() methods. Unless you have multiple threads involved, just see the synchronization mechanism as a bonus ;-)
A common idiom
final String[] result = { null };
result[0] = ...;
Looks good but I think you should make some kind of synchronization since another thread might set the value.
So, in a single parent inheritance model what's the best solution for making code extensible for future changes while keeping the same interface (I'd like to emphasize the fact that these changes cannot be known at the time of the original implementation, the main focus of my question is to explore the best mechanism/pattern for supporting these changes as they come up)? I know that this is a very basic OO question and below I provide example of how I've been going about it, but I was wondering if there a better solution to this common problem.
Here's what I've been doing (the example code is in Java):
In the beginning, the following two classes and interface are created:
public class Foo
{
protected int z;
}
public interface FooHandler
{
void handleFoo(Foo foo);
}
public class DefaultFooHandler implements FooHandler
{
#Override
public void handleFoo(Foo foo)
{
//do something here
}
}
The system uses variables/fields of type FooHandler only and that object (in this case DefaultFooHandler) is created in a few, well-defined places (perhaps there's a FooHandlerFactory) so as to compensate for any changes that might happen in the future.
Then, at some point in the future a need to extend Foo arises to add some functionality. So, two new classes are created:
public class ImprovedFoo extends Foo
{
protected double k;
}
public class ImprovedFooHandler extends DefaultFooHandler
{
#Override
public void handleFoo(Foo foo)
{
if(foo instanceof ImprovedFoo)
{
handleImprovedFoo((ImprovedFoo)foo);
return;
}
if(foo instanceof Foo)
{
super.handleFoo(foo);
return;
}
}
public void handleImprovedFoo(ImprovedFoo foo)
{
//do something involving ImprovedFoo
}
}
The thing that makes me cringe in the example above is the if-statements that appear in ImprovedFooHandler.handleFoo
Is there a way to avoid using the if-statements and the instanceof operator?
First of all the code you wrote won't work.
Each time you see instanceof and if...else together be very careful. The order of these checks is very important. In your case you'll never execute handleImpovedFoo. Guess why :)
It's absolutely normal you have these instanceof statements. Sometimes it's the only way to provide different behavior for a subtype.
But here you can use another trick: use simple Map. Map classes of foo-hierarchy to instances of fooHandler-hierarchy.
Map<Class<? extends Foo>, FooHandler> map ...
map.put( Foo.class, new FooHandler() );
map.put( ImprovedFoo.class, new ImprovedFooHandler() );
Foo foo ...; // here comes an unknown foo
map.get( foo.getClass() ).handleFoo( foo );
The best way of handling this depends too much on the individual case to provide a general solution. So I'm going to provide a number of examples and how I would solve them.
Case 1: Virtual File System
Clients of your code implement virtual file systems which enable them to operate any sort of resource which can be made to look like a file. They do so by implementing the following interface.
interface IFolder
{
IFolder subFolder(String Name);
void delete(String filename);
void removeFolder(); // must be empty
IFile openFile(String Name);
List<String> getFiles();
}
In the next version of your software you want to add the ability to remove a directory and all it contents. Call it removeTree. You cannot simply add removeTree to IFolder because that will break all users of IFolder. Instead:
interface IFolder2 implements IFolder
{
void removeTree();
}
Whenever a client registers an IFolder (rather then IFolder2), register
new IFolder2Adapter(folder)
Instead, and use IFolder2 throughout your application. Most of your code should not be concerned with the difference about what old versions of IFolder supported.
Case 2: Better Strings
You have a string class which supports various functionality.
class String
{
String substring(int start, end);
}
You decide to add string searching, in a new version and thus implement:
class SearchableString extends String
{
int find(String);
}
That's just silly, SearchableString should be merged into String.
Case 3: Shapes
You have a shape simulation, which lets you get the areas of shapes.
class Shape
{
double Area();
static List<Shape> allShapes; // forgive evil staticness
}
Now you introduce a new kind of Shape:
class DrawableShape extends Shape
{
void Draw(Painter paint);
}
We could add a default empty Draw method to Shape. But it seems incorrect to have Shape have a Draw method because shapes in general aren't intended to be drawn. The drawing really needs a list of DrawableShapes not the list of Shapes that is provided. In fact, it may be that DrawableShape shouldn't be a Shape at all.
Case 4: Parts
Suppose that we have a Car:
class Car
{
Motor getMotor();
Wheels getWheels();
}
void maintain(Car car)
{
car.getMotor().changeOil();
car.getWheels().rotate();
}
Of course, you know somewhere down the road, somebody will make a better car.
class BetterCar extends Car
{
Highbeams getHighBeams();
}
Here we can make use of the visitor pattern.
void maintain(Car car)
{
car.visit( new Maintainer() );
}
The car passes all of its component parts to calls into ICarVisitor interface allowing the Maintainer class to maintain each component.
Case 5: Game Objects
We have a game with a variety of objects which can be seen on screen
class GameObject
{
void Draw(Painter painter);
void Destroy();
void Move(Point point);
}
Some of our game objects need the ability to perform logic on a regular interval, so we create:
class LogicGameObject extends GameObject
{
void Logic();
}
How do we call Logic() on all of the LogicGameObjects? In this case, adding an empty Logic() method to GameObject seems like the best option. Its perfectly within the job description of a GameObject to expect it to be able to know what to do for a Logic update even if its nothing.
Conclusion
The best way of handling this situations depends on the individual situation. That's why I posed the question of why you didn't want to add the functionality to Foo. The best way of extending Foo depends on what exactly you are doing. What are you seeing with the instanceof/if showing up is a symptom that you haven't extended the object in the best way.
In situations like this I usually use a factory to get the appropriate FooHandler for the type of Foo that I have. In this case there would still be a set of ifs but they would be in the factory not the implementation of the handler.
Yes, don't violate LSP which is what you appear to be doing here. Have you considered the Strategy pattern?
This looks like a plain simple case for basic polymorphism.Give Foo a method named something like DontWorryI'llHandleThisMyself() (um, except without the apostrophe, and a more sensible name). The FooHandler just calls this method of whatever Foo it's given. Derived classes of Foo override this method as they please. The example in the question seems to have things inside-out.
With the visitor pattern you could do something like this,
abstract class absFoo {}
class Foo extends absFoo
{
protected int z;
}
class ImprovedFoo extends absFoo
{
protected double k;
}
interface FooHandler {
void accept(IFooVisitor visitor, absFoo foo);
}
class DefaultFooHandler implements FooHandler
{
public void accept(IFooVisitor visitor, absFoo foo)
{
visitor.visit(this, foo);
}
public void handleFoo(absFoo foo) {
System.out.println("DefaultFooHandler");
}
}
class ImprovedFooHandler implements FooHandler
{
public void handleFoo(absFoo foo)
{
System.out.println("ImprovedFooHandler");
}
public void accept(IFooVisitor visitor, absFoo foo) {
visitor.visit(this, foo);
}
}
interface IFooVisitor {
public void visit(DefaultFooHandler fooHandler, absFoo foo);
public void visit(ImprovedFooHandler fooHandler, absFoo foo);
}
class FooVisitor implements IFooVisitor{
public void visit(DefaultFooHandler fHandler, absFoo foo) {
fHandler.handleFoo(foo);
}
public void visit(ImprovedFooHandler iFhandler, absFoo foo) {
iFhandler.handleFoo(foo);
}
}
public class Visitor {
public static void main(String args[]) {
absFoo df = new Foo();
absFoo idf = new ImprovedFoo();
FooHandler handler = new ImprovedFooHandler();
IFooVisitor visitor = new FooVisitor();
handler.accept(visitor, idf);
}
}
But this does not guarantee only Foo can be passed to DefaultFooHandler. It allows ImprovedFoo also can be passed to DefaultFooHandler. To overcome, something similar can be done
class Foo
{
protected int z;
}
class ImprovedFoo
{
protected double k;
}
interface FooHandler {
void accept(IFooVisitor visitor);
}
class DefaultFooHandler implements FooHandler
{
private Foo iFoo;
public DefaultFooHandler(Foo foo) {
this.iFoo = foo;
}
public void accept(IFooVisitor visitor)
{
visitor.visit(this);
}
public void handleFoo() {
System.out.println("DefaultFooHandler");
}
}
class ImprovedFooHandler implements FooHandler
{
private ImprovedFoo iFoo;
public ImprovedFooHandler(ImprovedFoo iFoo) {
this.iFoo = iFoo;
}
public void handleFoo()
{
System.out.println("ImprovedFooHandler");
}
public void accept(IFooVisitor visitor) {
visitor.visit(this);
}
}
interface IFooVisitor {
public void visit(DefaultFooHandler fooHandler);
public void visit(ImprovedFooHandler fooHandler);
}
class FooVisitor implements IFooVisitor{
public void visit(DefaultFooHandler fHandler) {
fHandler.handleFoo();
}
public void visit(ImprovedFooHandler iFhandler) {
iFhandler.handleFoo();
}
}
public class Visitor {
public static void main(String args[]) {
FooHandler handler = new DefaultFooHandler(new Foo());
FooHandler handler2 = new ImprovedFooHandler(new ImprovedFoo());
IFooVisitor visitor = new FooVisitor();
handler.accept(visitor);
handler2.accept(visitor);
}
}