使用基本抽象类组合两个相似的类

时间:2018-09-04 18:08:24

标签: java inheritance abstract-class

我正在处理一个项目的请求请求,并被告知将两个相似类的代码组合成一个抽象类,这是另外两个类可以从中扩展的一个好主意。我的问题是我没有正确的方法来执行此操作。这是两个类:

public class ClassOne<OUT> extends RichInputFormat<OUT, InputSplit> implements NonParallelInput {
private static final Logger LOG = LoggerFactory.getLogger(ClassOne.class);

private final String query;
private final ClusterBuilder builder;

private transient Cluster cluster;
private transient Session session;
private transient Result<OUT> resultSet;
private Class<OUT> inputClass;

public ClassOne(String query, ClusterBuilder builder, Class<OUT> inputClass) {
    Preconditions.checkArgument(!Strings.isNullOrEmpty(query), "Query cannot be null or empty");
    Preconditions.checkArgument(builder != null, "Builder cannot be null");
    Preconditions.checkArgument(inputClass != null, "InputClass cannot be null");

    this.query = query;
    this.builder = builder;
    this.inputClass = inputClass;
}

@Override
public void configure(Configuration parameters) {
    this.cluster = builder.getCluster();
}

@Override
public BaseStatistics getStatistics(BaseStatistics cachedStatistics) throws IOException {
    return cachedStatistics;
}

/**
 * Opens a Session and executes the query.
 *
 * @param ignored
 * @throws IOException
 */
@Override
public void open(InputSplit ignored) throws IOException {
    this.session = cluster.connect();
    MappingManager manager = new MappingManager(session);

    Mapper<OUT> mapper = manager.mapper(inputClass);

    this.resultSet = mapper.map(session.execute(query));
}

@Override
public boolean reachedEnd() throws IOException {
    return resultSet.isExhausted();
}

@Override
public OUT nextRecord(OUT reuse) throws IOException {
    return resultSet.one();
}

@Override
public InputSplit[] createInputSplits(int minNumSplits) throws IOException {
    GenericInputSplit[] split = {new GenericInputSplit(0, 1)};
    return split;
}

@Override
public InputSplitAssigner getInputSplitAssigner(InputSplit[] inputSplits) {
    return new DefaultInputSplitAssigner(inputSplits);
}

/**
 * Closes all resources used.
 */
@Override
public void close() throws IOException {
    try {
        if (session != null) {
            session.close();
        }
    } catch (Exception e) {
        LOG.error("Error while closing session.", e);
    }

    try {
        if (cluster != null) {
            cluster.close();
        }
    } catch (Exception e) {
        LOG.error("Error while closing cluster.", e);
    }
}
}

第二个:

public class ClassTwo<OUT extends Tuple> extends RichInputFormat<OUT, InputSplit> implements NonParallelInput {
private static final Logger LOG = LoggerFactory.getLogger(ClassTwo.class);

private final String query;
private final ClusterBuilder builder;

private transient Cluster cluster;
private transient Session session;
private transient ResultSet resultSet;

public ClassTwo(String query, ClusterBuilder builder) {
    Preconditions.checkArgument(!Strings.isNullOrEmpty(query), "Query cannot be null or empty");
    Preconditions.checkArgument(builder != null, "Builder cannot be null");

    this.query = query;
    this.builder = builder;
}

@Override
public void configure(Configuration parameters) {
    this.cluster = builder.getCluster();
}

@Override
public BaseStatistics getStatistics(BaseStatistics cachedStatistics) throws IOException {
    return cachedStatistics;
}

/**
 * Opens a Session and executes the query.
 *
 * @param ignored
 * @throws IOException
 */
@Override
public void open(InputSplit ignored) throws IOException {
    this.session = cluster.connect();
    this.resultSet = session.execute(query);
}

@Override
public boolean reachedEnd() throws IOException {
    return resultSet.isExhausted();
}

@Override
public OUT nextRecord(OUT reuse) throws IOException {
    final Row item = resultSet.one();
    for (int i = 0; i < reuse.getArity(); i++) {
        reuse.setField(item.getObject(i), i);
    }
    return reuse;
}

@Override
public InputSplit[] createInputSplits(int minNumSplits) throws IOException {
    GenericInputSplit[] split = {new GenericInputSplit(0, 1)};
    return split;
}

@Override
public InputSplitAssigner getInputSplitAssigner(InputSplit[] inputSplits) {
    return new DefaultInputSplitAssigner(inputSplits);
}

/**
 * Closes all resources used.
 */
@Override
public void close() throws IOException {
    try {
        if (session != null) {
            session.close();
        }
    } catch (Exception e) {
        LOG.error("Error while closing session.", e);
    }

    try {
        if (cluster != null) {
            cluster.close();
        }
    } catch (Exception e) {
        LOG.error("Error while closing cluster.", e);
    }
}
}

区别在于Constructor(),open()和nextRecord()方法以及resultSet变量。另外ClassOne的类和ClassTwo的类。 我假设open和nextRecord方法只是不在抽象基类中实现它们,而将其留在ClassOne和ClassTwo中完成。但是抽象基类将需要具有构造函数,并且两个类具有不同的构造函数,并且基类必须具有或,这将使ClassOne或ClassTwo不起作用,具体取决于所使用的类型。我觉得自己正在忽略一个简单的解决方案。

感谢您的帮助!谢谢!

1 个答案:

答案 0 :(得分:3)

使用包含空构造函数的Java(和其他语言)抽象类是完全可能的。这样,您使用抽象类提供的两个类的组合可能看起来像这样:

public abstract class ClassAbstract extends RichInputFormat<OUT, InputSplit> implements NonParallelInput {

    private final String query;
    private final ClusterBuilder builder;
    private transient Cluster cluster;
    private transient Session session;

    public ClassAbstract(String query, ClusterBuilder builder) {
        Preconditions.checkArgument(!Strings.isNullOrEmpty(query), "Query cannot be null or empty");
        Preconditions.checkArgument(builder != null, "Builder cannot be null");
        this.query = query;
        this.builder = builder;
    }

    @Override
    public void configure(Configuration parameters) {
        this.cluster = builder.getCluster();
    }

    @Override
    public BaseStatistics getStatistics(BaseStatistics cachedStatistics) throws IOException {
        return cachedStatistics;
    }

    @Override
    public boolean reachedEnd() throws IOException {
        return resultSet.isExhausted();
    }

    @Override
    public InputSplit[] createInputSplits(int minNumSplits) throws IOException {
        GenericInputSplit[] split = {new GenericInputSplit(0, 1)};
        return split;
    }

    @Override
    public InputSplitAssigner getInputSplitAssigner(InputSplit[] inputSplits) {
        return new DefaultInputSplitAssigner(inputSplits);
    }

    /**
     * Closes all resources used.
     */
    @Override
    public void close() throws IOException {
        try {
            if (session != null) {
                session.close();
            }
        } catch (Exception e) {
            LOG.error("Error while closing session.", e);
        }

        try {
            if (cluster != null) {
                cluster.close();
            }
        } catch (Exception e) {
            LOG.error("Error while closing cluster.", e);
        }
    }

}

您的ClassOne构造函数可以简单地是:

    public ClassOne(String query, ClusterBuilder builder, Class<OUT> inputClass) {
        super(query, builder);
        Preconditions.checkArgument(inputClass != null, "InputClass cannot be null");
        this.inputClass = inputClass;
    }

ClassTwo的构造函数将变为:

    public ClassTwo(String query, ClusterBuilder builder) {
        super(query, builder);
    }

然后您可以通过扩展抽象类并删除抽象类中已经存在的所有代码来实例化子类。