V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
echooo0
V2EX  ›  程序员

父类的方法返回子类的对象问题

  •  
  •   echooo0 · Aug 18, 2022 · 2416 views
    This topic created in 1349 days ago, the information mentioned may be changed or developed.

    TradeResult 类继承 FrontResultBuilder 泛型类,在 FrontResultBuilder 返回子类的对象。

    现在想把子类的 static build 方法也移到 FrontResultBuilder 泛型类中,提示 cannot be referenced from a static context 错误,怎么破。。。。

    public abstract class FrontResultBuilder<T extends FrontResultBuilder<T>> {
        private String code;
        private String msg;
        abstract  T build();
        
        @SuppressWarnings( "unchecked" )
        public T code(String code) {
            this.code = code;
            return (T)this;
        }
     }
         
    public class TradeResult extends FrontResultBuilder<TradeResult> {
        private Date createTime;
        
        public static TradeResult build() {
            return new TradeResult();
     }
    }
     
    
    12 replies    2022-08-19 14:33:05 +08:00
    nothingistrue
        1
    nothingistrue  
       Aug 18, 2022
    你的工厂方法从底子上就是有问题的,没法破。工厂方法是主类的辅助类,可以是主类的内部类,但绝对不能跟主类有继承关系。

    继承关系上也有问题:构造方法和静态方法都是不能继承 /覆盖的。
    echooo0
        2
    echooo0  
    OP
       Aug 18, 2022
    @nothingistrue #1 不是为了继承覆盖,build 方法要做成 static 的,看起来泛型类里面不支持 static 方法,只能在子类里面做了。。。。
    Achieve7
        3
    Achieve7  
       Aug 18, 2022
    静态和构造方法是没法继承的, 做个 adapter 吧
    ccppgo
        4
    ccppgo  
       Aug 18, 2022
    FrontResultBuilder 写一个 buid 方法,不需要抽象, 然后把 Class 作为参数传进来, 用反射新建对象类似:

    ```
    public <T extends ParentClass> T paramInit(Class<T> clazz) {
    T param = null;
    param = clazz.newInstance();
    return param;
    }
    ```
    echooo0
        5
    echooo0  
    OP
       Aug 18, 2022
    @ccppgo #4 方法看上去不美观哈哈。。。用静态 build 方法就是想简洁一点。。。。。
    nothingistrue
        6
    nothingistrue  
       Aug 18, 2022
    private Class<T> templateClz;

    构造器上中
    templateClz= (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

    然后 public T code(String code) 这个方法就能正常用了。

    有限制条件,就是子类必须像你写的那样继承,即必须继承 BaseClass<SomeClass>,且这个 SomeClass 只能声明一次,后面再继承的类,T 是固定成 SomeClass 的,不能换。

    另外这个实际上解决的是,抽象父类中怎么获取子类的泛型的问题,这里正常的用法应该是 public abstract class FrontResultBuilder<T> , T 跟 FrontResultBuilder 没有继承关系。

    这种方法是用了泛型的黑科技,来自于 Hibernate ,现在已经基本不用了,用注解会更方便。
    ccppgo
        7
    ccppgo  
       Aug 18, 2022
    @echooo0 你这种静态 build 看你的代码还要每个继承的类写一遍。。。。那继承还有什么意义
    anonymous256
        8
    anonymous256  
       Aug 18, 2022   ❤️ 2
    没学过 java ,不过你的设计肯定是有问题的。
    基类就不应该调用派生类的任何东西,不管技术上能不能实现,你都不应该这么做。
    这是一个道德性原则。
    sutra
        9
    sutra  
       Aug 18, 2022
    static 跟父子没关系。
    echooo0
        10
    echooo0  
    OP
       Aug 18, 2022
    @ccppgo #7 贴出来的代码思路没理清楚。。。。v 站也没修改的按钮。。。
    sky857412
        11
    sky857412  
       Aug 19, 2022
    你中间需要一个工厂类,static 调不了用非 static 方法,abstract 也无法修饰 static 方法,设计的有问题
    echooo0
        12
    echooo0  
    OP
       Aug 19, 2022
    @sky857412 #11 大概的的设计思路是想在父类中,有个 build 方法来返回对应的子类对象,这就需要用到泛型,

    然后为了写起来简洁美观,这个 build 方法想设计成 static 的,但是泛型里面又没法有 static 方法,所以卡在这里。。。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3952 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 42ms · UTC 00:51 · PVG 08:51 · LAX 17:51 · JFK 20:51
    ♥ Do have faith in what you're doing.