I have an abstract parent class. He has two descendant classes. The fields of each of them are filled in by reading the data from the file along the specified path. Reading declare in the constructor of each descendant.

Tell me how to make it so that in the class of the parent it was possible to register in the constructor the reading of data, and in the descendant classes only to determine the paths to the necessary files?

public abstract class DSP { private ArrayList<Campaign> listOfCampaigns; private ArrayList<Campaign> filteredCampaigns; DSP(String[] campaignsPath){ listOfCampaigns = readListOfCampaigns(campaignsPath); } public double findBid(Request request){ // ΠŸΠ΅Ρ€Π²ΠΈΡ‡Π½Π°Ρ Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΡ filteredCampaigns = filterCampaigns(listOfCampaigns, request); return 1; } protected ArrayList<Campaign> filterCampaigns (ArrayList<Campaign> totalListOfCampaigns, Request request){ // Лист ΠΊΠ°ΠΌΠΏΠ°Π½ΠΈΠΉ, ΠΏΡ€ΠΎΡˆΠ΅Π΄ΡˆΠΈΡ… ΠΏΠ΅Ρ€Π²ΠΈΡ‡Π½Ρ‹ΠΉ ΠΎΡ‚Π±ΠΎΡ€ ArrayList<Campaign> listOfFilteredCampaigns = new ArrayList<Campaign>(); // Π¦ΠΈΠΊΠ» ΠΏΠΎ всСм Ρ€Π΅ΠΊΠ»Π°ΠΌΠ½Ρ‹ΠΌ кампаниям for ( int i = 0; i < totalListOfCampaigns.size(); i++ ){ // Π’ΠΎΡ‚ Ρ‚ΡƒΡ‚ Ρ‚ΠΎ ΠΈ Π²Ρ‹Π»Π΅Π·Π°Π΅Ρ‚ ошибка ... ... } protected static ArrayList<Campaign> readListOfCampaigns(String[] campaignsPath){ ArrayList<Campaign> listOfCampaigns = new ArrayList<Campaign>(); JAXBContext UnmarshallingClassJAXB = null; for ( int i = 0; i < campaignsPath.length; i++ ){ try { UnmarshallingClassJAXB = JAXBContext.newInstance(Campaign.class); } catch (JAXBException e1) { e1.printStackTrace(); } try { Campaign campaign = (Campaign) UnmarshallingClassJAXB.createUnmarshaller().unmarshal(new FileInputStream(campaignsPath[i])); listOfCampaigns.add(campaign); } catch (Exception e) { e.printStackTrace(); } } return listOfCampaigns; } 

    2 answers 2

    You can make the reading into the parent class method and pass it a File , String or InputStream , whichever is more convenient for you, from the constructor.

    If the read operation is an integral part of initialization, you can put it into the constructor of an abstract parent class (again, with a parameter of type File , String or InputStream ).


    Like that:

     public abstract class Parent { protected Parent(String filename) { System.out.println("reading file: " + filename); } } public class Child1 extends Parent { public Child1() { super("/some/file/path"); } } public class Child2 extends Parent { public Child2() { super("/another/file/path"); } } public class Main { public static void main(String args[]) { new Child1(); new Child2(); } } 
    • Yes, the read operation is an integral part of class initialization. Those. Can I just implement an abstract class constructor, and pass a path to the parameter quality? - Stas0n
    • @ Stas0n, added an example. System.out.println("reading file: " + filename); Replace the file reading. - Nofate ♦
    • The read data in the abstract class is stored in ArrayList <Campaign> listOfCampaigns There is another findBid method that also works with listOfCampaigns. It calls the filterCampaigns method, which is passed as parameters to the listOfCampaigns An error pops up - NullPointerException - Stas0n
    • Without seeing your code, it’s hard to tell where NPE comes from and because of what. - Nofate ♦
    • Added code to the topic - Stas0n

    In the ancestor you define a constructor that has one parameter - the name of the file. In the heirs with their constructor, call this constructor with the desired path.

    You can declare in the ancestor a separate protected method for loading, and call it from the heirs.

    Option three. A separate class is made which is able to correctly create the necessary class.

    • The first option is it really something different from the fact if you simply implemented your constructor in the heirs? - Stas0n
    • It differs in that the code is not duplicated in each successor. - Nofate ♦
    • those. Something similar to what Nofate wrote in his post below? - Stas0n
    • Yes. @Nofate has a good example. - KoVadim