V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
echooo0
V2EX  ›  程序员

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

  •  
  •   echooo0 · 2022-08-18 12:07:41 +08:00 · 1709 次点击
    这是一个创建于 820 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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 条回复    2022-08-19 14:33:05 +08:00
    nothingistrue
        1
    nothingistrue  
       2022-08-18 12:39:30 +08:00
    你的工厂方法从底子上就是有问题的,没法破。工厂方法是主类的辅助类,可以是主类的内部类,但绝对不能跟主类有继承关系。

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

    ```
    public <T extends ParentClass> T paramInit(Class<T> clazz) {
    T param = null;
    param = clazz.newInstance();
    return param;
    }
    ```
    echooo0
        5
    echooo0  
    OP
       2022-08-18 16:53:07 +08:00
    @ccppgo #4 方法看上去不美观哈哈。。。用静态 build 方法就是想简洁一点。。。。。
    nothingistrue
        6
    nothingistrue  
       2022-08-18 17:28:57 +08:00
    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  
       2022-08-18 18:51:13 +08:00
    @echooo0 你这种静态 build 看你的代码还要每个继承的类写一遍。。。。那继承还有什么意义
    anonymous256
        8
    anonymous256  
       2022-08-18 19:44:36 +08:00   ❤️ 2
    没学过 java ,不过你的设计肯定是有问题的。
    基类就不应该调用派生类的任何东西,不管技术上能不能实现,你都不应该这么做。
    这是一个道德性原则。
    sutra
        9
    sutra  
       2022-08-18 19:53:50 +08:00
    static 跟父子没关系。
    echooo0
        10
    echooo0  
    OP
       2022-08-18 21:03:27 +08:00
    @ccppgo #7 贴出来的代码思路没理清楚。。。。v 站也没修改的按钮。。。
    sky857412
        11
    sky857412  
       2022-08-19 12:11:07 +08:00
    你中间需要一个工厂类,static 调不了用非 static 方法,abstract 也无法修饰 static 方法,设计的有问题
    echooo0
        12
    echooo0  
    OP
       2022-08-19 14:33:05 +08:00
    @sky857412 #11 大概的的设计思路是想在父类中,有个 build 方法来返回对应的子类对象,这就需要用到泛型,

    然后为了写起来简洁美观,这个 build 方法想设计成 static 的,但是泛型里面又没法有 static 方法,所以卡在这里。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2258 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 00:51 · PVG 08:51 · LAX 16:51 · JFK 19:51
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.