【问题标题】:Construction of parent abstract class父抽象类的构造
【发布时间】:2020-09-14 04:25:50
【问题描述】:

Java 新手在这里。 我有两个类(我们称它们为 A 和 B),它们包含的一些方法(例如 doSomething(...))非常相似,因为它们实际上共享相同的代码。我决定让我的代码更有效,并使用某种父抽象类 C,类 A、B 将从该类继承。

这是我的问题。 A 类中的方法 doSomething 具有以下签名:

doSomething(VievForA view, ...)

虽然 B 类中的相同方法 doSomething 具有如下签名:

doSomething(VievForB view, ...)

如您所见,doSomething 方法使用不同类型的第一个参数,所以我不知道如何在抽象类中解决这个问题。

构造类 C 的正确方法是什么?方法 doSomething 应该是什么样的? 希望我能很好地解释我的情况,否则我可以添加更多伪代码。

【问题讨论】:

    标签: java oop model-view-controller abstract-class


    【解决方案1】:

    您还可以有一个基视图类,它将被 ViewA 和 ViewB 继承,并使用 ViewBase 作为 doSomething 的参数。

    【讨论】:

    • 这个解决方案解决了子类 A 和 B 上的 doSomething 签名问题(如果需要对这些类进行显式强制转换,则为事件),但它需要更多的东西来帮助避免在特定实现上重用通用代码
    【解决方案2】:

    您可以使用 Java 泛型来构建您的代码,如下所示:

    // View Classes
    //====    
    
    /**
     * The generic view parent class
     */
    public abstract class GenericView{
    }
    
    /**
     * The specific A view class
     */
    public class ViewForA extends GenericView{
        //...
    }
    
    /**
     * The specific B view class
     */
    public class ViewForB extends GenericView{
        //...
    }
    
    // View Handler Classes
    //====
    
    /**
     * The generic view handler
     * @param <T> The view object that extends from GeneriView
     */
    public abstract class C<T extends GenericView>{
    
        private void doGenericSomething(GenericView t) {
            //Do something generic on all views
        }
    
        //Do something specific on specific view
        abstract void doSpecificSomething(T t);
    
        //Do all stuff
        protected void doSomething(T t){
            doGenericSomething(t);
            doSpecificSomething(t);
        }
    
    }
    
    /**
     * The specific A view handler
     */
    public class A extends C<ViewForA>{
    
        @Override
        void doSpecificSomething(ViewForA view) {
            //Do your stuff with viewForA
        }
    }
    
    /**
     * The specific B view handler
     */
    public class B extends C<ViewForB>{
    
        @Override
        void doSpecificSomething(ViewForB view) {
            //Do your stuff with viewForB
        }
    }
    

    这样你就可以在 C 类的doGenericSomething(GenericView t) body 上插入你的common代码,然后让每个特定的视图类,例如 A 和 B 类来实现 特定的 doSpecificSomething(ViewForSpecific t) 上的代码,其中 ViewForSpecific 是一个继承自 GenericView 的类(如共享代码中的 ViewForA 和 ViewForB )。

    【讨论】:

    • 这很有趣!您能否详细说明使用 this 与仅使用普通子类的优势?你现在确实有一个额外的课程。这值得努力吗?
    • “使用普通子类”具体是什么意思?还有这个解决方案添加的附加类是什么?
    • 我的意思是A、B、C、C
    • 你为什么把 C 报告为类?可能你不知道 Java 泛型。检查 Java 文档中的通用语法,以使我的示例代码具有正确的含义。
    【解决方案3】:

    你可以使用一个通用的继承类作为方法的参数:

    doSomething(CommonViev view, ...)
    {
       if (view instanceof VievForA)
       {
          VievForA vievForA = (VievForA)view;
          ...
       }
       else if (view instanceof VievForB)
       {
          VievForB vievForB = (VievForB)view;
          ...
       }
    }
    

    【讨论】:

    • instanceof 在这种情况下非常有用。虽然我会尝试使用“最小的公共父级”作为参数类型。 Object 确实是有史以来最伟大的共同父母,然后可以使用 doSomething("myString");doSomething(1.23); 调用该方法
    • 是的,你是对的。我会更好地创建一个通用接口或抽象类。但是,我写这个只是作为例子。
    • 你分享的这个方法应该放在C类上吗?如果是,为什么打算通用的 C 类应该包含特定对象的代码,如 vievForA 和 vievForB?此外,如果您引入另一个特定对象(如 vievForC),则应更新 C 类,由于其通用目的而应将其用作库,因此应尽可能减少更改。在构建代码时避免使用 instanceof 也是一个好习惯(请参阅这篇有趣的文章:armedia.com/blog/instanceof-avoid-in-code
    • 非常感谢。这很有趣,你的例子很有说明性。
    【解决方案4】:

    如果您试图维护扩展 C 的两个类 A 和 B, 然后在 C 类中,你可以这样声明。

    doSomething(Object view, ...)
    
    

    在 A 类或 B 类中,如下所示使用

    doSomething(Object view, ...){
    
    VievForA(B) vievForA(B) = (VievForA(B)) view;     //basically typecast it as per child class
    
    }
    
    

    【讨论】:

    • 可以,但是我不知道是哪个类调用了方法,所以我无法确定是转换为A还是转换为B。
    • @Roberto Fernández Iglesias 的回答能回答这个问题吗?
    【解决方案5】:

    假设您的doSomething() 有重复的代码,您可以在abstractC 中实现通用代码,并在AB 的实现中使用它。

    abstract class C {  
        protected Result doSomething(CommonStuff common){
            // doing common stuff and
            return result;  // returning the result
        }
    } 
    
    
    class A extends C { 
        public void doSomething(ViewForA view, ..){
             CommonStuff common = view.getStuff();
             Result result = this.doSomething(common);
             view.applyResult(result);
        }
    }
    

    但这是非常……抽象的例子。如果您的 ViewForA 和 ViewForB 有任何类型的通用接口,那么使用它会更好。一旦我像这样使用通用接口:

     abstract class C {
    
          abstract protected ViewInterface getView();
    
          protected void doSomething(){
               this.getView().doStuffWithView();
          }
     }
    
    
     class A extends C {
         private ViewForA myViewForA; 
    
         @Override
         protected ViewForA getView(){
              return this.myViewForA;
         }
      }
    

    然后抽象类可以处理doSomething,假设将使用任何类型的公共视图实例。而A类和B类会自动实现共同的doSomething,你可以像这样使用它

    A a = new A();
    a.doSomething();
    

    【讨论】:

      猜你喜欢
      • 2015-03-20
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 2011-08-01
      • 2018-11-29
      • 2011-03-16
      • 1970-01-01
      相关资源
      最近更新 更多