简体   繁体   English

抽象类从实现子类获取参数?

[英]Abstract class get parameter from implementing subclass?

I'm wondering if there is way to do this without breaking encapsulation, I want the abstract class to rely on parameters defined in the implementing subclass. 我想知道是否存在不破坏封装的方法,我希望抽象类依赖于实现子类中定义的参数。 Like so: 像这样:

public abstract class Parent {

    private int size;
    private List<String> someList;

    public Parent() {
        size = getSize();
        someList = new ArrayList<String>(size);
    }

    public abstract int getSize();

}

public class Child extends Parent {

    @Override
    public int getSize() {
        return 5;
    }

}

Is this ugly? 这很丑吗? Is there a better way? 有没有更好的办法? And perhaps more importantly, is this even a good idea? 也许更重要的是,这是否是个好主意?

EDIT: 编辑:

The classes are created in the context of a framework, so the default parameter-less constructor is always the one called (in fact, the Parent class extends another class). 这些类是在框架的上下文中创建的,因此默认的无参数构造函数始终是被调用的构造函数(实际上,Parent类扩展了另一个类)。 The size parameter is just used for illustration purposes and I don't plan on using it for a List implementation. size参数仅用于说明目的,我不打算将其用于List实现。

No, is not ugly. 不,不难看。 This pattern is named "template method". 该模式称为“模板方法”。 But typically it is more useful when the method is not a simple getter but something that implement business logic. 但是通常,如果该方法不是简单的获取方法,而是实现业务逻辑的方法,则它会更有用。

In your case other solution is to define protected constructor in Parent class and call it with relevant parameter from child: 在您的情况下,另一种解决方案是在Parent类中定义受保护的构造函数,并使用child中的相关参数进行调用:

public abstract class Parent {

    private int size;
    private List<String> someList;

    protected Parent(int size) {
        this.size = size;
        someList = new ArrayList<String>(size);
    }

    public int getSize() {
        return size;
    }

}

public class Child extends Parent {
    public Child() {
        super(5);
    }
}

If the constructor is the only place you use getSize() , just require it as a constructor parameter. 如果构造函数是您使用getSize()的唯一位置,则只需将其作为构造函数参数即可。

But more importantly, why do you care about size? 但更重要的是,为什么要关心尺寸? Unless you know there's a problem, just use the default size like everybody else: 除非您知道有问题,否则像其他所有人一样使用默认大小:

public abstract class Parent {

    private List<String> someList = new ArrayList<String>();

    // use default constructor    
}

The pattern is not ugly, except when you try to use it in the constructor. 该模式并不难看,除非您尝试在构造函数中使用它。 It allows you to modify Child in a way that results are unexpected. 它允许您以意外的方式修改Child。

public class Child extends Parent {

    private int mySize = 5;

    @Override
    public int getSize() {
        // The -1 is only to help clarify what happens
        return mySize - 1;
    }

}

If you now create an instance of Child it would actually throw an exception because a negative capacity is not allowed. 如果现在创建Child的实例,则实际上将引发异常,因为不允许负容量。 You should realize that the properties of a class are only initialized after the parent constructor has finished. 您应该意识到,仅在父构造函数完成后才初始化类的属性。 (And if a property is set using the Parent constructor and has a default value defined in Child, it will happily overwrite the value you just set in Parent() ) (如果属性是使用Parent构造函数设置的,并且在Child中定义了默认值,那么它将很乐意覆盖您刚刚在Parent()中设置的值)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM