14

以下の方法で何か方法はないかと考えております。抽象クラスShapeとそのすべての異なるサブクラスがあり、クローン メソッドをオーバーライドしたいと考えています。このメソッドでやりたいことは、現在のメソッドShapeから新しいメソッドを作成することtoString()だけです。Shape明らかに、抽象的であるため、次のことはできません。単純な名前の変更のためだけにすべてのサブクラスでクローンをオーバーライドすることは役に立たないように見えるため、これを行う別の方法はありますか?

public abstract class Shape {

    public Shape(String str) {
        // Create object from string representation
    }

    public Shape clone() {
        // Need new way to do this
        return new Shape(this.toString());   
    }

    public String toString() {
        // Correctly overriden toString()
    }
}
4

4 に答える 4

2

良いアイデアだとは思いませんが、リフレクションを使用できます。

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test {

    public static void main(String[] args) {        
        Square s1 = new Square("test");
        Square s2 = (Square) s1.clone();

        // show that s2 contains the same data  
        System.out.println(s2);
        // show that s1 and s2 are really different objects
        System.out.println(s1 == s2);
    }

    public static abstract class Shape {
        private String str;

        public Shape(String str) {
            this.str = str;
        }

        public Shape clone() {          
            try {
                Class<?> cl = this.getClass();
                Constructor<?> cons = cl.getConstructor(String.class);
                return (Shape) cons.newInstance(this.toString());           
            } catch (NoSuchMethodException | SecurityException |
                     InstantiationException | IllegalAccessException |
                     IllegalArgumentException | InvocationTargetException e) {  
                e.printStackTrace();
            }           

            return null;
        }

        @Override
        public String toString() {
            return str;
        }
    }

    public static class Square extends Shape {
        public Square(String str) {
            super(str);
        }
    }   
}
于 2013-08-09T12:22:07.197 に答える
2

インスタンス化できないため、クラスのディープ クローンを作成できません。できることは、使用または返却による浅いクローン作成だけですabstractObject.clone()this

@Override
public Object clone() throws CloneNotSupportedException {
    return super.clone();
}

また

@Override
public Object clone() throws CloneNotSupportedException {
    return this;
}

抽象クラスは参照として機能できますが、インスタンスを持つことはできないため、この場合は浅い複製が機能します

また

より良いアプローチとして、次のように宣言clone()abstract、子クラスにそれを定義するように依頼できます。

abstract class Shape {

    private String str;

    public Shape(String str) {
        this.str = str;
    }

    public abstract Shape clone();

    public String toString() {
        return str;
    }
}

class Circle extends Shape {

    public Circle(String str) {
        super(str);
    }

    @Override
    public Shape clone() {
        return new Circle("circle");
    }

}
于 2013-08-09T12:14:07.383 に答える
1

リフレクションで解決できます:

public abstract class Shape {

    private String str;

    public Shape()  {

    }

    protected Shape(String str) {
        this.str = str;
    }

    public Shape clone() throws CloneNotSupportedException
    {
        try {
            return (Shape)getClass().getDeclaredConstructor(String.class).newInstance(this.toString());
        } catch (Exception e) {
            throw new CloneNotSupportedException();
        }
    }

    public String toString() {
        return "shape";
    }

public class Round extends Shape
{
    public Round()
    {
        super();
    }
    protected Round(String str) {
        super(str);
    }

    @Override
    public String toString() {
        return "round";
    }
}

main(){
  Shape round = new Round();        
  Shape clone = round.clone();
  System.out.println(round);
  System.out.println(clone);
}

しかし - IMO - 実装が不十分で、エラーが発生しやすく、多くのピットがあります。の最善の使い方はCloneableObject.clone()それらを使用しないことです。フローをより適切に制御できるようにするために、同じこと (ディープ クローンのシリアライゼーションなど) とシャロー クローンを実行する方法がたくさんあります。

于 2013-08-09T12:22:14.623 に答える