有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何与任何类共享自返回方法链?

更新:我明白了!原来蜘蛛鲍里斯的“泛型”评论正是我需要的线索

首先是原始问题和中断的代码,下面是解决方案。下面是我为needer needable所做的通用设计

原始问题和非工作代码

在过去的几年中,我断断续续地试图使自返回方法链与其他类“共享”。这是为了避免在每个子类中复制每个自返回函数的巨大痛苦。基本思想是将“needer”类传递给“needable”类以开始配置,然后在配置完成后将needer传递回。“所需”对象是在内部设置的

例如:

ConfigUser cu = (new ConfigUser()).
   cfgFavNum().twentySeven().increment().timesTwo().endCfg().
   firstName("Kermit").lastName("Frog");

在哪里

firstName("Kermit").lastName("Frog")

是ConfigUser类的一部分,并且

twentySeven().increment().timesTwo().endCfg()

来自单独的“配置编号”类endCfg()返回“needer”类(ConfigUser),此时您应该能够继续ConfigUser中的链。但是你不能。在下面的代码中。。。我每次尝试都会犯同样的错误:

        C:\java\ConfigUser.java:4: cannot find symbol
        symbol  : method firstName(java.lang.String)
        location: interface NeedsFavNum
                 cfgFavNum().twentySeven().increment().timesTwo().endCfg().
                                                                          ^

如果在endCfg()之后注释掉所有内容,则会发现问题:

ConfigUser cu = (new ConfigUser()).
   cfgFavNum().twentySeven().increment().timesTwo().endCfg();//.
   //firstName("Kermit").lastName("Frog");

         C:\java\ConfigUser.java:15: incompatible types
         found   : NeedsFavNum
         required: ConfigUser
                        cfgFavNum().twentySeven().increment().timesTwo().endCfg();//.
                                                                               ^

它不能返回ConfigUser,这是NeedsFavNum的子类,它是所有“需要”最喜爱的数字配置的类的接口

当然,您可以复制所有函数,以便它们都返回ConfigUser-s,但这违背了共享链的目的。目的是在任何类之间共享这些链,而不仅仅是子类

有没有办法做到这一点,或者重新思考整个问题?我开始认为这根本不可能

详细信息在下面的代码中。它可以工作(…无论如何,直到出现这些编译错误):将其复制到名为ConfigUser的文件中。java并尝试一下

谢谢你帮助我

public class ConfigUser implements NeedsFavNum  {
   public static final void main(String[] igno_red)  {
      ConfigUser cu = (new ConfigUser()).
         cfgFavNum().twentySeven().increment().timesTwo().endCfg().
         firstName("Kermit").lastName("Frog");

      cu = (new ConfigUser()).                  cfgFavNum().twentySeven().increment().timesTwo().endCfg();//.
      //         firstName("Kermit").lastName("Frog");
   }
//init
   public static final int iDEFAULT_FAV = 8;
   int iFav = -1;
   String sName1st = null;
   String sNameLast = null;
//funcs
   public ConfigUser()  {
   }
   public ConfigUser firstName(String s_s)  {
      sName1st = s_s;
   }
   public ConfigUser lastName(String s_s)  {
      sNameLast = s_s;
   }
   public FavNumConfigurator cfgFavNum()  {
      return  new FavNumConfigurator(this, iDEFAULT_FAV);
   }
   public ConfigUser setNumReturnNeeder(int i_favFullyConfigured)  {
      iFav = i_favFullyConfigured;
      return  this;
   }
}
interface NeedsFavNum  {
   ConfigUser setNumReturnNeeder(int i_fav);
}
class FavNumConfigurator  {
   NeedsFavNum nfn = null;
   int iFav = -1;
   public FavNumConfigurator(NeedsFavNum nf_n, int i_defaultFav)  {
      nfn = nf_n;
      iFav = i_defaultFav;
   }
   public FavNumConfigurator twentySeven()  {
      iFav = 27;
   }
   public FavNumConfigurator timesTwo()  {
      iFav = iFav * 2;
   }
   public FavNumConfigurator increment()  {
      iFav += 1;
   }
   public NeedsFavNum endCfg()  {
      return  nfn.setNumReturnNeeder(iFav);
   }
}

具有工作代码的解决方案

原来蜘蛛鲍里斯的“泛型”评论正是我需要的线索。而不是“需要的”类

FavNumConfigurator

现在是

FavNumConfigurator<R extends FavNumNeeder>

其中FavNumNeeder是任何需要favorite number配置链的类的“needer”接口。现在endCfg()函数可以准确地返回我想要的类

下面是一个固定的示例(它可以工作——复制并保存为ConfigUser.java):

/**
   <P>The main class: the &quot;needer&quot;.</P>
 **/
public class ConfigUser implements NeedsFavNum  {
   public static final void main(String[] igno_red)  {
      ConfigUser cu = (new ConfigUser()).
         cfgFavNum().twentySeven().increment().timesTwo().timesTwo().endCfg().
         firstName("Kermit").lastName("Frog");

      System.out.println("name:         " + cu.sName1st + " " + cu.sNameLast);
      System.out.println("favorite-num: " + cu.iFav);

      //---OUTPUT:
      //name:         Kermit Frog
      //favorite-num: 112
   }
//init
   public static final int iDEFAULT_FAV = 8;
   int iFav = -1;
   String sName1st = null;
   String sNameLast = null;
//funcs
   public ConfigUser()  {
   }
   //Self-returning configurers...START
      public ConfigUser firstName(String s_s)  {
         sName1st = s_s;
         return  this;
      }
      public ConfigUser lastName(String s_s)  {
         sNameLast = s_s;
         return  this;
      }
   //Self-returning configurers...END
   //Start fav-num configuration. Returns the "needable"
   public FavNumConfigurator<ConfigUser> cfgFavNum()  {
      return  (new FavNumConfigurator<ConfigUser>(this, iDEFAULT_FAV));
   }
   //Called by the "needable" in endCfg()
   public ConfigUser setNumReturnNeeder(int i_favFullyConfigured)  {
      iFav = i_favFullyConfigured;
      return  this;
   }
}

//The "needer" interface, for all classes needing favorite-number
//configuration
interface NeedsFavNum  {
   ConfigUser setNumReturnNeeder(int i_fav);
}

//The "needable" class: A shareable function-chain for favorite-number
class FavNumConfigurator<R extends NeedsFavNum>  {
   R nfn = null;
   int iFav = -1;
   public FavNumConfigurator(R nf_n, int i_defaultFav)  {
      nfn = nf_n;
      iFav = i_defaultFav;
   }
   //Self-returning configurers...START
      public FavNumConfigurator<R> twentySeven()  {
         iFav = 27;
         return  this;
      }
      public FavNumConfigurator<R> timesTwo()  {
         iFav = iFav * 2;
         return  this;
      }
      public FavNumConfigurator<R> increment()  {
         iFav += 1;
         return  this;
      }
   //Self-returning configurers...END
   public R endCfg()  {
      nfn.setNumReturnNeeder(iFav);
      return  nfn;
   }
}

通用针刺可需设计

下面是我设计的一个实现上述修复的通用needer-needable解决方案。最困难的部分是避免ConfigNeedableConfigNeeder之间的循环依赖

public interface Chainable  {
   Chainable chainID(Object o_id);
   Object getChainID();
}
public interface ConfigNeedable<O,R extends ConfigNeeder> extends Chainable  {
   boolean isAvailableToNeeder();
   ConfigNeedable<O,R> startConfigReturnNeedable(R c_n);
   R getActiveNeeder();
   boolean isNeededUsable();
   R endCfg();
}
public interface ConfigNeeder  {
   void startConfig();
   boolean isConfigActive();
   <O> Class<O> getNeededType();
   <O> void setNeeded(O o_fullyConfigured);
}

这里是使用此设计的同一个(工作)示例,但由于它取决于我的个人库中的实现(目前尚未发布,因为它在我工作时每分钟都在变化),因此它不会编译。希望它能帮助别人看到

import  xbn.lang.chain.ChainableComposer;
import  xbn.lang.chain.ConfigNeeder;
import  xbn.lang.chain.SimpleConfigNeedable;
import  xbn.lang.chain.SimpleConfigNeeder;

public class ConfigNeedableNeederXmpl  {
   public static final void main(String[] igno_red)  {
      UserSettings us = (new UserSettings()).
         cfgFavInt().twentySeven().timesTwo().increment().endCfg().name("President Obama");
      System.out.println("name=" + us.sName);
      System.out.println("favorite number=" + us.iFav);
   }
}
class UserSettings implements ConfigNeeder  {
   private SimpleConfigNeeder scn = new SimpleConfigNeeder(Integer.class);
   public static final int iDEFAULT_FAV = 8;
   public int iFav = -1;
   public String sName = null;

   public UserSettings name(String s_name)  {
      sName = s_name;
      return  this;
   }
   public FavNumConfigurator cfgFavInt()  {
      FavNumConfigurator fnc = new FavNumConfigurator();
      fnc.startConfigReturnNeedable(this);
      return  fnc;
   }
   //ConfigNeeder: composition implementation...START
      public <O> void setNeeded(O i_fullyConfigured)  {
         scn.setNeeded(i_fullyConfigured);
         iFav = (Integer)scn.getElimNeeded();
      }
      public void startConfig()  {
         scn.startConfig();
      }
      public boolean isConfigActive()  {
         return  scn.isConfigActive();
      }
      public <O> Class<O> getNeededType()  {
         return  scn.getNeededType();
      }
      public void endConfig()  {
         iFav = (Integer)scn.getElimNeeded();
      }
   //ConfigNeeder: composition implementation...END
}
class FavNumConfigurator extends SimpleConfigNeedable<Integer,UserSettings>  {
   public FavNumConfigurator()  {
      super(33, true);
   }
   public FavNumConfigurator(Integer o_defaultNeeded, boolean b_defaultNeededUsable)  {
      super(o_defaultNeeded, b_defaultNeededUsable);
   }
   public FavNumConfigurator set(int i_i)  {
      try  {
         updateObject(i_i);
      }  catch(RuntimeException rtx)  {
         throw  newRTXWChainID("set", rtx);
      }
      return  this;
   }
   public FavNumConfigurator twentySeven()  {
      updateObject(27);
      return  this;
   }
   public FavNumConfigurator timesTwo()  {
      updateObject(getNeededInProcess() * 2);
      return  this;
   }
   public FavNumConfigurator increment()  {
      updateObject(getNeededInProcess() + 1);
      return  this;
   }
}

共 (1) 个答案

  1. # 1 楼答案

    你所要寻找的是有效的C++ Curiously recurring template pattern

    您可以将所有“共享”自返回位放入一个基本抽象类中,然后对其进行扩展

    例如:

    public abstract class Base<T extends Base<T>>
    {
       protected abstract T self(); 
    
       protected String name;
       protected String address;
    
       public T withtName(String name)
       {
           this.name = name;
           return self();
        }
    
       public T withAddress(String address)
       {
           this.address = address;
           return self();
       }
    
    }
    
    class MyClass extends Base<MyClass>
    {
        private String someOtherThing;
    
        public MyClass withSomeOtherThing(String thing)
        {
            this.someOtherThing = thing;
            return self();
        }
    
        @Override
        protected MyClass self()
        {
            return this;
        }    
     }
    

    现在您可以执行以下操作:

    MyClass mc = 
        new MyClass()
            .withAddress("111 elm")
            .withtName("Bob")
            .withSomeOtherThing("foo");