【问题标题】:collapse parent and child java classes in eclipse在eclipse中折叠父子java类
【发布时间】:2014-12-29 15:51:32
【问题描述】:

我继承了一个只有一个子类的抽象父类,两者都在 单独的文件。

它们又大又丑。而且它们的结构不再正确。 我将把它们重构得更好——但作为其中的一部分,我会 首先喜欢将它们折叠成一个类。 IE。从这样的事情出发:

public abstract class ParentClass implements SomeInterface {

   ParenClass(SomeOtherClass v) {
     aMember = v;
   }

   @NonNull final SomeOtherClass aMember;

   abstract void doSomething();

   // Several hundred lines of other functions and members.
}

public class ChildClass extends ParentClass {

    ChildClass(AnotherClass v2) {
       super(v2.getSomething());
       this.childMember = v2.somethingElse();
    }

    @NonNull final SomeOtherClass aMember;

    @Override void doSomething() {
      //...
    }

    // Several hundred lines of other functions and members
}

到两个类的合并版本(实际上可以命名为 原来的类虽然......)

public class MergedParentAndChild implements SomeInterface {

   JustOneClass(AnotherClass v2) {
      this.aMember = v2.getSomething();
      this.childMember = v2.somethingElse();
   }

   void doSomething() {
      //...
   }
   // Lots of other functions etc.
}

我已经在所有成员上使用“上拉”重构手动完成了这项工作,但这很耗时,因为 它让构造函数出错,并且在最终成员和抽象函数等方面存在问题。

也许 Eclipse 可能有一种快速的方法可以直接在其重构列表中执行此操作。就是找不到。

有没有快速简便的方法来做到这一点?

【问题讨论】:

  • 你需要重构什么?抱歉,来晚了,我好像想不通XD
  • 我正在尝试用一个类替换不必要的两个类层次结构。分离成父类和子类是不合适的(或不再合适)并且妨碍了进一步的重构。我可以手动完成,或者在每个函数/字段上使用“上拉”重构,一个接一个,但不幸的是有很多成员,以及有类似问题的大量类。
  • 我的回答是否令人困惑? XD对不起,如果是

标签: java eclipse refactoring


【解决方案1】:

其实这可以通过内联类来完成。

首先,你需要将子类方法拉到父类;

然后,您可以内联子类。 (Intellij Idea,将光标放在子类上,refactor->inline。Intellij Idea 将删除子类,并将子类替换为父类)

【讨论】:

    【解决方案2】:

    使用“上拉”重构并不像我最初想象的那样重复/痛苦。我将借用 JClassic 的示例并稍作修改(使其更糟)并展示会发生什么

    这是原始代码。

    public class Temp {
    
        public static interface I1 {
            public void interfaceFn1();
            public void interfaceFn2();
        }
    
        public static abstract class A implements I1 {
            int a;
            public void foo(){
                System.out.printf("%s In A a=%d\n", this, a);
            }
    
            @Override public void interfaceFn1() {
                System.out.println("In A.interfaceFn1");
            }
        }
    
        public static class AA extends A {
            int aa;
    
            @Override 
            public void foo(){
                super.foo();
                System.out.printf("%s In AA a=%d, aa=%d\n", this, a , aa);
            }
    
            @Override public void interfaceFn2() {
                System.out.println("In A.interfaceFn1");
            }
        }
    }
    

    如果您随后将光标放在 AA 中的某个函数上并选择“ “上拉”重构。 (Alt+Shift+T, U) - 你会看到以下对话框。

    然后点击右侧的全选,然后点击下一步。

    您会在如下所示的对话框中收到有关重复函数的警告,这将导致编译错误。您可以忽略这些,稍后再修复它们。

    然后你会得到如下所示的代码:

    public class Temp {
    
        public static interface I1 {
            public void interfaceFn1();
            public void interfaceFn2();
        }
    
        public static abstract class A implements I1 {
            int a;
            int aa;
            public void foo(){
                System.out.printf("%s In A a=%d\n", this, a);
            }
    
            @Override public void interfaceFn1() {
                System.out.println("In A.interfaceFn1");
            }
    
            @Override public void foo() {
                super.foo();
                System.out.printf("%s In AA a=%d, aa=%d\n", this, a , aa);
            }
    
            @Override public void interfaceFn2() {
                System.out.println("In A.interfaceFn1");
            }
        }
    
        public static class AA extends A {
        }
    }
    

    您现在可以删除类AA 并修复A 中的错误(重复foo() 是主要问题)。产生这样的代码:

    public class Temp {
    
        public static interface I1 {
            public void interfaceFn1();
            public void interfaceFn2();
        }
    
        public static abstract class A implements I1 {
            int a;
            int aa;
            private void fooBase(){
                System.out.printf("%s In A.fooBase a=%d\n", this, a);
            }
    
            @Override public void interfaceFn1() {
                System.out.println("In A.interfaceFn1");
            }
    
            public void foo() {
                fooBase();
                System.out.printf("%s In AA a=%d, aa=%d\n", this, a , aa);
            }
    
            @Override public void interfaceFn2() {
                System.out.println("In A.interfaceFn1");
            }
        }
    }
    

    剩下的最大问题是将AA 的所有创建/引用切换到A。但是,如果您选择了use destination type where possible,这将减少您需要修复的位置数量。

    我怀疑在某些情况下构造函数会导致一些问题,但在大多数情况下这似乎没问题。

    【讨论】:

      【解决方案3】:

      自动化两个层次类的组合真的很难(如果不是不可能的话):考虑以下情况:你有两个类

      public static class A {
          int a;
          public void foo(){
              //do stuff
          }
      }
      
      public static class AA extends A {
          int aa;
      
          @Override 
          public void foo(){
              //do stuff
          }
      }
      

      当你合并它们时,你会遇到问题:

      public static class AMerged{
          int a;
          int aa; //this is fine
          public void foo(){ //but use who's implementation?
              //do what?
          }
      }
      

      这样,你会遇到方法名称相同的问题,变量相同,我将使用谁的实现?孩子还是父母?如您所见,合并两个您会遇到的类有很多问题,因此自动化几乎是不可能的。

      即使是抽象类,也没有办法将它们组合起来,只能手动完成

      【讨论】:

        猜你喜欢
        • 2012-11-12
        • 2010-10-31
        • 1970-01-01
        • 1970-01-01
        • 2011-03-26
        • 1970-01-01
        • 2014-03-24
        • 2011-07-23
        • 2022-08-19
        相关资源
        最近更新 更多