writing good abstract classes in java - java

I have the following need and please help me to write good and abstract class.
Different types of operations is needed based on the type
I have a abstract class,
abstract public class FileHelper{
//Template method
//This method defines a generic structure for parsing data
public void parseDataAndGenerateFile(String fileDownloadType)
{
createHeader(fileDownloadType);
generateFile();
}
//We have to write output in a excel file so this step will be same for all subclasses
public void createHeader(String fileDownloadType)
{
System.out.println('Creating HEADER in EXCEL');
}
public void generateFile(String fileDownloadType)
{
System.out.println('Output generated,writing to XLX');
}
}
public class ExcelDataParser extends FileHelper {
String fileDownloadType="";
}
public class TemplateMethodMain {
public static void main(String[] args) {
String fileDownloadType="expired";
ExcelDataParser csvDataParser=new ExcelDataParser();
csvDataParser.parseDataAndGenerateFile(fileDownloadType);
}
}
Please help me and correct me to have a good way of doing this.

If you want to use an abstract base class, you better should declare an abstract method String getDownloadType() in your abstract base class. These method must be overridden by the derived classes and the type could be fix in the derived class.
For example:
abstract public class FileHelper {
abstract String getFileDownloadType();
public void parseDataAndGenerateFile() {
createHeader();
generateFile();
}
public void createHeader() {
if ("expired".equals(getFileDownloadType())) {
} else {
}
}
public void generateFile() {
if ("expired".equals(getFileDownloadType())) {
} else {
}
}
}
public class ExcelDataParser extends FileHelper {
#Override
String getFileDownloadType() {
return "expired";
}
}
public class TemplateMethodMain {
public static void main(String[] args) {
ExcelDataParser csvDataParser = new ExcelDataParser();
csvDataParser.parseDataAndGenerateFile();
}
}
But if you don't need a class for every type, you also could make the type a variable inside a single class and passing the type to the contructor
For example:
public class CsvFileHelper {
private final String fileDownloadType;
public CsvFileHelper(String type) {
fileDownloadType = type;
}
public void parseDataAndGenerateFile() {
createHeader();
generateFile();
}
public void createHeader() {
if ("expired".equals(fileDownloadType)) {
} else {
}
}
public void generateFile() {
if ("expired".equals(fileDownloadType)) {
} else {
}
}
}
public class TemplateMethodMain {
public static void main(String[] args) {
CsvFileHelper csvDataParser = new CsvFileHelper("expired");
csvDataParser.parseDataAndGenerateFile();
}
}

Related

Raw use of parameterized class - when returning base class with generic parameter with factory design pattern

Background
I learned Factory pattern, and the power of generics and I'm attempting to piece them together.
Here are my efforts
Without generic input parameter - No warnings
public abstract class ArtifactCreator {
public abstract void setArtifacts(String workflowInput);
}
public class FooArtifactCreator extends ArtifactCreator {
#Override
public void setArtifacts(String input) {
return null;
}
}
public class BarArtifactCreator extends ArtifactCreator {
#Override
public void setArtifacts(String input) {
return null;
}
}
public class Factory {
public ArtifactCreator getArtifactCreator(String domain) {
if (domain == "foo") {
return new FooArtifactCreator()
} else if (domain == "bar") {
return new BarArtifactCreator()
}
return null;
}
}
My whole problem is the workflowInput is relegated to the type String. But I want it to be some generic POJO.
With generics - I get warnings in Factory.java and Store.java that I want to get rid of correctly. (I want to be using generics for my use-case the right way).
Raw use of parameterized class 'ArtifactCreator' on both the files in Store.java and Factory.java
Unchecked call to 'setArtifacts(T)' as a member of raw type 'ArtifactCreator' in Store.java
public abstract class ArtifactCreator {
public abstract void setArtifacts(T workflowInput);
}
public class FooArtifactCreator extends ArtifactCreator<FooInput> {
#Override
public void setArtifacts(FooInput input) {
return null;
}
}
public class BarArtifactCreator extends ArtifactCreator<BarInput> {
#Override
public void setArtifacts(BarInput input) {
return null;
}
}
public class Factory {
public ArtifactCreator getArtifactCreator(String domain) {
if (domain == "foo") {
return new FooArtifactCreator()
} else if (domain == "bar") {
return new BarArtifactCreator()
}
return null;
}
}
public class Input {
private String domain;
private String otherInput;
}
public class Store {
private final Factory factory;
public Store(Factory factory) {
this.factory = factory;
}
public ArtifactCreator getCaseClosureArtifactFactory(Input req) {
ArtifactCreator artifactCreator = factory.setArtifacts(req.getDomain());
//In reality - Create either FooInput or BarInput depending on
//`otherInput` field in `Input` POJO. Assume that there will be another
//factory/HashMap to return the input needed
FooInput input = new FooInput();
artifactCreator.setArtifacts(input);
}
}
One way I can think of solving my problems is do something like:
public class WorkflowInput {
private FooInput input;
private BarInput input;
}
public abstract class ArtifactCreator {
public abstract void setArtifacts(WorkflowInput workflowInput);
}
public class FooArtifactCreator extends ArtifactCreator {
#Override
public void setArtifacts(WorkflowInput input) {
FooInput input = input.getFooInput(); //Extract specific input
}
}
public class BarArtifactCreator extends ArtifactCreator {
#Override
public void setArtifacts(WorkflowInput input) {
BarInput input = input.getBarInput(); //Extract specific input
}
}
This feels a bit unecessary to keep some fields in WorkflowInput null.

How to use a parameter of type `Derived` in a overridden method accepting `Base`?

I have the following situation:
abstract class Base {
int data = 0;
void baseMethod() {
System.out.println("baseMethod:" + data);
}
}
class DerivedA extends Base {
void DerivedBMethodA() {
}
void usefulMethod(Something something) {
something.doSomething(this);
}
interface Something {
void doSomething(DerivedA deriv);
}
}
class DerivedB extends Base {
void DerivedMethodB() {
}
}
public class Temp {
public static void main() {
DerivedA a = new DerivedA();
a.usefulMethod(new DerivedA.Something() {
#Override
public void doSomething(DerivedA deriv) {
deriv.DerivedBMethodA();
}
});
}
}
I want to push usefulMethod and Something upto the Base class so that DerivedB can leverage it. And I want implementations of Something.doSomething to be able to use a derived type, so that it can access derived functionality.
How do I do that?
Attempts
I've tried the following:
abstract class Base {
int data = 0;
void baseMethod() {
System.out.println("baseMethod:" + data);
}
void usefulMethod(Something something) {
something.doSomething(this);
}
interface Something {
void doSomething(Base deriv);
}
}
class DerivedA extends Base {
void DerivedBMethodA() {
}
}
class DerivedB extends Base {
void DerivedMethodB() {
}
}
public class Temp {
public static void main() {
DerivedA a = new DerivedA();
a.usefulMethod(new Base.Something() {
#Override
public void doSomething(DerivedA deriv) {
deriv.DerivedBMethodA();
}
});
}
}
but that fails as my anonymous Something doesn't implement doSomething(Base). So trying to use generics:
I tried:
interface Something {
void doSomething(<? extends Base> deriv);
}
but that won't compile due to: "Wildcards may be used only as reference parameters"
I tried:
interface Something {
<T extends Base> void doSomething(T deriv);
}
but that requires me to implement the interface as so:
a.usefulMethod(new Base.Something() {
#Override
public <T extends Base> void doSomething(T deriv) {
}
});
which obviously doesn't allow me access to the derived type?
There are ways I can make it "work" but they're undesirable:
This:
interface Something {
void doSomething(Base deriv);
}
a.usefulMethod(new Base.Something() {
#Override
public void doSomething(Base deriv) {
DerivedA a1 = (DerivedA) deriv;
a1.DerivedBMethodA();
}
});
But that requires me to cast in each implementation, which seems wasteful.
And this:
package com.miurasample.ui.info;
abstract class Base {
int data = 0;
void baseMethod() {
System.out.println("baseMethod:" + data);
}
void usefulMethod(Something something) {
something.doSomething(this);
}
interface Something<T extends Base> {
void doSomething(T deriv);
}
}
public class Temp {
public static void main() {
DerivedA a = new DerivedA();
a.usefulMethod(new Base.Something<DerivedA>() {
#Override
public void doSomething(DerivedA deriv) {
}
});
}
}
but that results in a warning/IDE highlight in usefulMethod of:
"Unchecked call to doSomething(T) as a member of raw type Base.Something"
What's the tersest and "cleanest" way to do this? Is that I'm doing even sane?
It is difficult to say if your design is wrong or not. We dont have full scope of your requirements to assert that, but here is clean non cast approach to what you are trying to do. It does require extra method in your derived classes:
public static void main(String... args) {
DerivedA a = new DerivedA();
a.usefulMethod( new Base.Something<DerivedA>() {
#Override
public void doSomething(DerivedA deriv) {
deriv.DerivedBMethodA();
}
} );
}
public abstract static class Base< T extends Base<T> > {
int data = 0;
protected abstract T getThis();
void baseMethod() {
System.out.println("baseMethod:" + data);
}
void usefulMethod(Something<T> something) {
something.doSomething( getThis() );
}
interface Something< T extends Base<T> > {
void doSomething(T deriv);
}
}
public static class DerivedA extends Base<DerivedA> {
protected DerivedA getThis(){
return this;
}
void DerivedBMethodA() {}
}
public static class DerivedB extends Base<DerivedB> {
protected DerivedB getThis(){
return this;
}
void DerivedMethodB() {}
}

How to pass down the new operator in a method

For example, if I wanted to do something like this to call a method:
myLights.addLight(new Fluorescent(lumens));
in order to create a new object in the Fluorescent class and pass down the lumens data. How would I then set up the method to receive this?
Assuming method is not returning anything.
void addlight(Fluorescent a){
// your logic
}
In your Lights class create a method that accepts a Fluorescent object as an argument.
public void addLight(Fluorescent fluorescent){
// do something
}
Here is a basic example:
public class HelloWorld
{
public static void main(String[] args)
{
Light light = new Light();
light.addLight(new Fluorescent("300 lm"));
System.out.print(light.getLumen());
}
}
public class Light {
private String lumen;
public Light() {
}
public void setLumens(String lumen){
this.lumen = lumen;
}
public String getLumen(){
return this.lumen;
}
public void addLight(Fluorescent fluorescent) {
if(fluorescent.getLumen() != null) {
this.lumen = fluorescent.getLumen();
}
}
}
public class Fluorescent {
private String lumen;
public Fluorescent(String lumen){
this.lumen = lumen;
}
public void setLumen(String lumen){
this.lumen = lumen;
}
public String getLumen(){
return this.lumen;
}
}
Seeing that a Fluorescent is a Light, you might want to look in to inheritance.
Look here for some explanation
Java 101: Inheritance in Java, Part 1
public class Fluorescent() {
public Fluorescent(String lumens) {
// do something
}
}
public class Lights() {
public void addLight(Fluorescent fluorescent) {
// do something
}
}

Using method of one class from another class using 'this' keyword in constructor

I have two nested classes inside a class with the outer class extending another class. The structure is something like this.
public class EXTENSION_CLASS
{
public int Get_Value()
{
return(100);
}
}
public class OUTER extends EXTENSION_CLASS
{
public static class NESTED1
{
public void Method1()
{
int value=0;
value=Get_Value();
System.out.println("Method1: "+value);
}
}
public static class NESTED2
{
NESTED1 Nested1_Instance=new NESTED1();
public void Method2()
{
Nested1_Instance.Method1();
}
}
public void run()
{
NESTED2 Nested2_Instance=new NESTED2();
Nested2_Instance.Method2();
}
public static void main (String[] args)
{
OUTER New_Class=new OUTER();
New_Class.run();
}
}
I'm expecting the output: "Method1: 100". But, am getting the output: "OUTER.java:16: error: non-static method Get_Value() cannot be referenced from a static context value=Get_Value();". How can i make this working?
Cheers !
Rajesh.
One approach would be to have an instance of NESTED1 in NESTED2. For example:
private static class NESTED2
{
private NESTED1 nested1;
public NESTED2 (NESTED1 nested1) {
this.nested1 = nested1;
}
public void Method2()
{
nested1.Method1();
}
}
private static class NESTED2
{
public void Method2(NESTED1 nested1Instance)
{
nested1Instance.Method1();
}
}
That should do it with your class structure. Instead, with a modification like so....
private static class NESTED1
{
public *statc* void Method1()
{
...
}
}
private static class NESTED2
{
public *static* void Method2()
{
NESTED1.Method1();
}
}
... you could get away with no creation of objects.
If you make the methods static, you don't need to instantiate(create) a class object to call them first.

Generics specific interface definition in Java

Is it possible to define following in Java:
public interface IGenericRepo<T> {
void add();
void delete();
void attach();
}
public interface IGenericRepo<Book> {
default String bookSpecificMethod(){
return "smthn";
}
}
public class NHGenericRepo<T> implements IGenericRepo<T>{
/* implementation */
}
public class NHUnitOfWork implements UnitOfWork{
#Autowired
public void setBookRepo(NHGenericRepo<Book> bookRepo) {
this.bookRepo= bookRepo;
}
public NHGenericRepo<Book> getBookRepo() {
return bookRepo;
}
private NHGenericRepo<Book> bookRepo;
}
And to be able somewhere in code to have:
{
#Autowired
public void setNhuw(NHUnitOfWork nhuw) {
this.nhuw = nhuw;
}
private NHUnitOfWork nhuw;
/**/
{
String st = this.nhuw.getBookRepo().bookSpecificMethod();
}
}
In .net this is possible by using Extension Method with "this IGenericRepo<Book>" as a first method parameter.
The closest you can come is:
public interface IBookGenericRepo extends IGenericRepo<Book> {
void BookSpecificMethod();
}

Categories

Resources