1

Instantiate an abstract class. -> Duplicate it, preserving the implementation of the abstract method.

    public abstract class Foo{… 

    public int myVar;

    public abstract void do();

     }//Foo

elsewhere in package:

public class Gha{ … 

    Foo testFoo = new Foo{

        @Override
        public void do(){
            Log.i("" , "this is a special Foo"); //executable process
        }//do

    }//testFoo
    …
}//Gha

Can I copy testFoo in a way that copies testFoo’s .do() method body for the new Foo?

Scottie
  • 23
  • 6
  • 1
    You cannot call a method `do`. Why do you need to do this? What is the point in having two separate instances for executing the same block of code? – Paul Boddington Apr 14 '16 at 20:13
  • Mind adding indentation to your code snippets? It's very hard to read. – Egor Apr 14 '16 at 20:15
  • Ty. Attempted to make the code more readable. @Egor – Scottie Apr 14 '16 at 20:22
  • @PaulBoddington I'm using many `Foo` and they each have a different method of reacting. They are also used as instance variables, and I need to make a deep copy. – Scottie Apr 14 '16 at 20:25
  • Not...really? Objects are not, in general, copyable. Without a named class, you're almost certainly out of luck. Besides, the `Foo` in your example appears stateless, so there wouldn't be any point in copying it anyway? – Louis Wasserman Apr 14 '16 at 20:29
  • Related: http://stackoverflow.com/questions/19188882/can-you-clone-an-anonymous-object-java-oop – azurefrog Apr 14 '16 at 20:29
  • @azurefrog Thanks, I'll edit. Wrote these snippets just to post here. The actual code uses the proper `"` – Scottie Apr 14 '16 at 20:32
  • @azurefrog good catch. It's not an exact duplicate, but the difference is minor enough that I think functionally it's the same:: http://stackoverflow.com/questions/19188882/can-you-clone-an-anonymous-object-java-oop – Scottie Apr 14 '16 at 20:36

2 Answers2

2

You could use clone. The use of this method is widely discouraged, but it does work.

For example:

public abstract class Foo implements Cloneable {

    private int a;
    private String b;

    public Foo(int a, String b) {
        this.a = a;
        this.b = b;
    } 

    public abstract void run();

    public int getA() { return a; }

    public String getB() { return b; }

    @Override
    public final Foo clone() {
        try {
            return (Foo) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new AssertionError(); // Can't happen
        }
    }
}

Then, you can do:

Foo original = new Foo(3, "bar") {
    @Override
    public void run() {
        System.out.println("Hello, world!");
    }
};
Foo copy = original.clone();
System.out.println(copy.getA());
System.out.println(copy.getB());
copy.run();
System.out.println(copy == original);

The output is:

3
bar
Hello, world!
false

An alternative is to use Serializable.

public abstract class Foo implements Serializable {

    private int a;
    private String b;

    public Foo(int a, String b) {
        this.a = a;
        this.b = b;
    }

    public abstract void run();

    public int getA() { return a; }

    public String getB() { return b; }

    public final Foo copy() {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            new ObjectOutputStream(baos).writeObject(this);
            return (Foo) new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())).readObject();
        } catch (Exception e) {
            throw new AssertionError(); 
        }
    }
}

With this version, replace clone by copy and you'll get the same result.

Paul Boddington
  • 37,127
  • 10
  • 65
  • 116
  • Clone seems like a good fit. I really like your first solution. Thank you. I'll poke around to find out why it's so discouraged. I never really explored it before. – Scottie Apr 14 '16 at 20:51
  • @Scottie I recommend Effective Java by Josh Bloch. There's an excellent section on `clone`. The main irritation is that `clone` is not `public`, so if you have a `List extends Cloneable>` you can't actually make a deep copy, because you can't call `clone` on the elements. It's ridiculous. – Paul Boddington Apr 14 '16 at 20:53
  • 1
    @Scottie Josh Bloch doesn't like it, nuff said :P – zgc7009 Apr 14 '16 at 20:54
  • Thanks, I will pick it up! – Scottie Apr 14 '16 at 21:09
1

You can do this...

public class TestFoo extends Foo{

    private static String TAG = TestFoo.class.getSimpleName();

    @Override
    public void do(){
        Log.i(getTag() , “this is a special Foo”); //executable process
    }

    protected String getTag(){
        return TAG;
    }
}

And then instantiate TestFoo objects that will perform do(). If you want a separate Tag for each instance you can override the getTag() function in the instanted class. Not sure if this is what you need but a lot easier to explain than a comment :P

NOTE

If this is something you would be doing in a lot of places, and you don't want to subclass all over the place (mentioned in the comments) please look at Paul Boddington's answer, particularly the copy portion.

zgc7009
  • 3,371
  • 5
  • 22
  • 34
  • Yep, that would work, thank you. That's actually how it's now, but I was/ am trying to cut down on the clutter of a whole pile of sub-classed `Foo`s. – Scottie Apr 14 '16 at 20:30
  • @Scottie It sounds like you may want to sit down and rethink how you are working your app. If Foo get's overridden by a bunch of subclasses you should just use an interface. – zgc7009 Apr 14 '16 at 20:32
  • The actual `Foo` would have instance variables. I will update the question. @zgc7009 – Scottie Apr 14 '16 at 20:37
  • @Scottie What is the purpose of the var? If the purpose of the var is to use it in do, just pass it to do as a parameter and return whatever you need instead of void. – zgc7009 Apr 14 '16 at 20:41
  • I missed it on first read. Never thought to use the `getSimpleName()` . I think this solves my issue. I'll store all the method bodies in a separate resource file and call them based on a switch. Thanks so much! EDIT: actually, no it doesn't, but adding a int flag and then sending to a switch would. Thanks for putting me on the right track. ;) Still kinda awkward, but functional. – Scottie Apr 14 '16 at 20:44