9 – Please help me understand “Class not found” error

I’ve set up a very basic Drupal 9 website to educate myself about how to program modules for this version of Drupal.

I am trying to do create a module named “Hello World” that implements a very simple service that basically has a method to return “Hello World”.

I’ve registered this service as follows in hello_world.services.yml:

services:
  hello_world.salutation:
    class: Drupalhello_worldHelloWorldSalutation

The service itself lives in a a file named HelloWorldSalutation.php in the src/ subdirectory of the project. It looks like this:

namespace Drupalhello_world;
class HelloWorldSalutation {
  public function getSalutation() {
    return 'Hello world';
  }
}

I am trying to use this service in hello_world.module by means of the following line

$service = Drupal::service('hello_world.salutation');

After a cache rebuild, this results in:

Error: Class 'Drupalhello_worldHelloWorldSalutation' not found in DrupalComponentDependencyInjectionContainer->createService() (line 257 of core/lib/Drupal/Component/DependencyInjection/Container.php).

I am unable to grasp what the problem is. The system is clearly looking up the service name (“hello_world.salutation“), and translates this into the class “HelloWorldSalutation” in the “Drupalhello_world” namespace, which I believe exists. But then the error message says that this class does not exist.

It is probably something obvious I’ve overlooked, but I’ve spent the best part of the day on this, and I am not able to figure it out. Please help.

object oriented – Python – Pagination class

I built a small flask app and a lot of routes do need some kind of pagination system. However, in some cases I would like to just display n-2, n-1, n, n+1, n+2 where n is the current page and in some others cases, probably a bigger range. Fo example, in the following picture, the range is 2. I am probably going to merge increase() and decrease() in a single method.

I am not doing any database call here, I just want to perform pagination calculation and return values in a form of a dictionary in order to be used by different flask modules.

Would appreciate a feedback! I am quite new to this industry

enter image description here

import math

class Pagination():
    def __init__(self, total_items, items_per_page, page_range, current_page=0):
        self.total_items = total_items  # total number of article to display in total
        self.items_per_page = items_per_page  # maximum number of article per page
        self.page_range = page_range  # number of previous and next pages to display
        self.current_page = current_page
        self.number_of_pages = math.ceil(
            self.total_items / self.items_per_page)

        # if the current_page is 7 and page_range is 3 then self.following will be (8, 9, 10) and self.previous (4, 5 ,6)
        self.following = list(
            range(self.current_page + 1, self.current_page + self.page_range + 1))

        # empty because by default the current page is 0 so no previous
        self.previous = list()


    def increase(self, quantity):
        if self.current_page + quantity > self.number_of_pages:
            raise ValueError(
                f'The maximum number of pages is {self.number_of_pages}')
        else:
            self.current_page += quantity
            self.following = list()
            self.previous = list()
            for i in range(1, self.page_range + 1):
                new_following_page_number = i + self.current_page
                new_previous_page_number = self.current_page - i
                self.previous.insert(i, new_previous_page_number)

                # make sure the number does not exceed the number of pages 
                if new_following_page_number < self.number_of_pages:
                    self.following.insert(i, new_following_page_number)


    def decrease(self, quantity):
        if self.current_page - quantity < self.number_of_pages:
            raise ValueError(f'The mimimum number of pages is 0')
        else:
            self.current_page -= quantity
            self.following = list()
            self.previous = list()
            for i in range(1, self.page_range + 1):
                new_following_page_number = i + self.current_page
                new_previous_page_number = self.current_page - i
                self.following.insert(i, new_following_page_number)
                if new_previous_page_number > 0:
                    self.previous.insert(i, new_previous_page_number)
       
       
    # method called to set the MongoDB skip amount
    def number_of_previous_items(self):
        if self.current_page == 0:
            return 0
        return self.items_per_page * self.current_page


    # method called to inject variables in the pagination HTML nav
    def dict(self):
        return {
            "current_page": self.current_page,
            "next_page": self.following,
            "previous_page": self.previous,
            "number_of_pages": self.number_of_pages
        }

tmp.py

items_pagination = Pagination(total_items=150, items_per_page=10, page_range=3)
print(render.dict())
render.increase(4)
print(render.dict())

results

{'current_page': 0, 'next_page': (1, 2, 3), 'previous_page': (), 'number_of_pages': 15}
{'current_page': 4, 'next_page': (5, 6, 7), 'previous_page': (3, 2, 1), 'number_of_pages': 15}

    

random – This code is a non-static C# class for rolling a number of dice

Fellow human beings, today I present to you my dice rolling script! Behold, in my amateurish attempt at some raw C# code. Perhaps this will remain here regardless of the dozens of other dice rolling scripts out there.

Contains a ‘for’ loop, a ‘switch’, and a method that returns a value.

I have indeed read through other, similar iterations of this class, and I have found them to be lacking in what I might learn from, usually due to over-complication for my tiny brain, or because it invoked the use of libraries I have yet to hear of.

I did my best to make it easy to read for whichever intrigued person stumbles upon this. I deeply respect and appreciate any who may take the time to offer any criticism on my code. What did I do right? What did I do wrong? I don’t have anyone or anywhere else to share it with.

using System;

namespace C_
{
    class RollDice : Program
    {


        //Variables

        int numOfDice;
        int numOfSides;

        int maxDice = 100;
        int minDice = 1;
        int maxSides = 100;
        int minSides = 1;
        int totalRolled;

        //Start method for number of Dice to throw - take the player input in InputMethod() which returns an int. If returning 0, then restart. Clamp the value between min/max. Continue to next function.

        public void GetDice()
        {
            Console.WriteLine("Welcome to Roll Dice!");
            Console.WriteLine("How many dice do you want to throw?");
            numOfDice = InputMethod();
            if(numOfDice == 0)
            {
                GetDice();
            }
            if (numOfDice > maxDice || numOfDice < minDice)
            {
                numOfDice = Math.Clamp(numOfDice, minDice, maxDice);
                Console.WriteLine($"Number of Dice set to {numOfDice}");
            }

            GetSides();
        }

        // Get the sides of each dice by using a similar process. Roll() for each dice, then sum the totals in RollTotal().

        public void GetSides()
        {
            Console.WriteLine("How many sides does each dice have?");
            numOfSides = InputMethod();
            if(numOfSides == 0)
            {
                GetSides();
            }
            if (numOfSides > maxSides || numOfSides < minSides)
            {
                numOfSides = Math.Clamp(numOfSides, minSides, maxSides);
                Console.WriteLine($"Number of Sides set to {numOfSides}");
            }

            for (int x = 1; x <= numOfDice; x++)
            {
                Roll();
            }

            RollTotal();
        }


        // Create a new Random() instance for the number of sides and add it to the totalRolled variable.

         public void Roll()
        {
            Console.WriteLine(".....");
            Console.WriteLine("Rolling");
            Random r = new Random();
            var result = r.Next(1, numOfSides + 1);
            Console.WriteLine($"You rolled {result}");
            totalRolled += result;
        }
        
        // Output the total and prompt to roll again or quit. Reset the total..

        public void RollTotal()
        {
            Console.WriteLine($"Total sum rolled is {totalRolled}");
            Console.WriteLine(" ");
            Console.WriteLine("Enter 1 to re-roll or 2 to quit.");
            var answer = InputMethod();

            switch (answer)
            {
                case 0:
                RollTotal();
                break; 
            
                case 1:
                totalRolled = 0;
                GetDice();
                break;           
            
                case 2:
                totalRolled = 0;
                Environment.Exit(0);
                break;
            
                default:
                Environment.Exit(0);
                break;
            }
        }

        //Convert the input to an integer if valid and return the value. Else return 0.

        public int InputMethod()
        {
            var input = Console.ReadLine();
            if(!Int32.TryParse(input, out int convertedStringToInt))

            {
                Console.WriteLine("You need to enter a valid number!");
                return 0;
            }
            
            else 
            
            {
                return Convert.ToInt32(input);
            }

        }

    }
}

python – PyQt5 developing complex Window GUI and making everything its own class

TLDR: Is my code following best practices for OOP and PyQt5 regarding inheritance, and is it okay to initialise classes within another class? What can I do to improve my methods, or what would be a better approach to my specific problem?

I’m very new to OOP and PyQt5. My Code creates a GUI with 2 tab widgets, each with multiple tabs, and each tab with its own layouts and widgets.

To make the code manageable (in my beginner opinion), I’ve turned everything into a class. The Window class handles the Window and Layout and creates instances of the tab widgets. The Tabs classes handle Tab layouts and create instances of tablets (pages). The Tablet class handles tablets and their layouts and adds widgets such as buttons, labels etc.

Window Layout

Versions:

python                 3.7.3
PyQt5                  5.15.4
PyQt5-Qt5              5.15.2
PyQt5-sip              12.8.1

CODE

"""
Initialises Window, Sets out the geometry management, and adds Widgets
"""
import sys

from PyQt5.QtCore import pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import (
  QApplication, QGridLayout, QMainWindow, QTableWidgetItem, QWidget
)

from PyQt5.QtWidgets import (
  QComboBox, QFormLayout, QHBoxLayout, QVBoxLayout,
  QLabel, QPushButton, QTabWidget, QTableWidget, QWidget
)


class Window(QMainWindow):
    """Create an instance of Window. Sets up main Window"""
    # my_signal = pyqtSignal(int)
    def __init__(self):
        super().__init__()
        self.setMinimumSize(1000, 800)
        self.centralWgt = QWidget()  # create central widget
        self.setCentralWidget(self.centralWgt)  # set central widget
        self.tabIn = InputTab()  # create input tab widget
        self.tabOut = OutputTab()  # create input tab widget
        self.windowLayout()  # set window layout

        # TODO: Move this and "test" to a class to keep Window minimal
        self.tabIn.tablet1.btnApply.clicked.connect(self.test)

    def test(self):
        """
        When tabIn tablet1 btnApply pressed, Do something in tabOut tablet1
        """
        self.tabOut.tablet1.textGreeting.setText(“Hello”)
        print("Here!")

    def windowLayout(self):
        """Handles the main windows layout"""
        self.layout = QGridLayout()
        self.centralWgt.setLayout(self.layout)
        self.layout.addWidget(self.tabIn, 0, 1)  # Add widgets to layout
        self.layout.addWidget(self.tabOut, 1, 1, 2, 1)  # Add widgets to layout
        # Handle window and widget resizing
        self.layout.setColumnStretch(0, 1)
        self.layout.setColumnStretch(1, 1)
        self.layout.setRowStretch(0, 1)
        self.layout.setRowStretch(1, 1)
        self.layout.setRowStretch(2, 1)


# TAB MANAGEMENT


class Tabs(QTabWidget):
    """Tabs master class"""
    def __init__(self):
        super().__init__()
        self.tabs = QTabWidget()  # Initialise Tab Widget
        self.layout = QVBoxLayout()  # Define Tab Widget Layout
        self.setLayout(self.layout)  # Set Tab Widget Layout
        self.setStyleSheet('QTabBar { font-size: 12pt;}')  # Set tab title size


class InputTab(Tabs):
    """Creates and sets up the InputTab Class. Inherits from Tab Class"""
    def __init__(self):
        super().__init__()
        self.tablet1 = ItemTablet(QWidget())  # Initialise tablet
        self.tabs.addTab(self.tablet1, "Item Queries")  # Add tablet
        self.layout.addWidget(self.tabs)  # Add tablets to layout


class OutputTab(Tabs):
    """Creates and sets up the OutputTab Class. Inherits from Tab Class"""
    def __init__(self):
        super().__init__()
        self.tablet1 = TableTablet(QWidget())  # Initialise tablet
        self.tabs.addTab(self.tablet1, "Output - Item Table")  # Add tablet
        self.layout.addWidget(self.tabs)  # Add tablets to layout


# TABLET MANAGEMENT #


class Tablets(QTableWidget):
    """The Tablets master class. Contains shared methods, variables"""
    def __init__(self, widget):
        super().__init__()
        self.widget = widget  # set tablet widget as given widget type
        self.layout = QVBoxLayout()  # create tablet outer layout
        self.setLayout(self.layout)  # set tablet outer layout
        self.setStyleSheet('font-size: 10pt;')  # Set tablet font size

    def populateForm(self, formFields):
        """Populates a form layout with dict key value pairs"""
        for k, v in formFields.items():
            self.frmLayout.addRow(k, v)  # Add items to tablet form layout

    def stdButtons(self):
        """Adds Apply and Clear buttons to bottom of tablet."""
        self.btnApply = QPushButton(text="Apply")
        self.btnClear = QPushButton(text="Clear")
        self.btnLayout.addWidget(self.btnApply)
        self.btnLayout.addWidget(self.btnClear)

    def stdFormLayout(self):
        """Creates a Form with horizontal buttons at bottom"""
        self.frmLayout = QFormLayout()  # create tablet sublayout
        self.btnLayout = QHBoxLayout()  # create tablet sublayout
        self.layout.addLayout(self.frmLayout)  # set tablet sublayout
        self.layout.addLayout(self.btnLayout)  # set tablet sublayout


class ItemTablet(Tablets):
    """Handles Item Tablet"""
    def __init__(self, widget):
        super().__init__(widget)
        self.stdFormLayout()  # choose stdFormLayout as a sublayout
        self.stdButtons()  # add stdButtons to sublayout
        # create form items
        self.lblItems = QLabel("Item name")
        self.cmbItems = QComboBox()
        self.cmbItems.addItems(("1", "2", "3"))

        # add form items to dict to setup widget associations
        self.formFields = {
            self.lblItems: self.cmbItems,
        }
        self.populateForm(self.formFields)  # add items to form layout


class TableTablet(Tablets, QTableWidget):
    """Handles the output table tablet"""
    def __init__(self, widget):
        super().__init__(widget)
        self.style = "::section{Background-color:lightgray;border-radius:9px;}"
        self.header = self.horizontalHeader()
        self.header.setStyleSheet(self.style)
        self.textGreeting = QLineEdit()
        self.layout.addWidget(self.textGreeting)


if __name__ == "__main__":
    app = QApplication(())
    window = Window()
    window.show()
    sys.exit(app.exec_())

c++ – Rcpp sparse CSC matrix class

This is a sparse matrix (dgCMatrix) class that extends Rcpp.

WHAT: This class includes Rcpp::NumericVector and Rcpp::NumericMatrix classes which are simple references to R objects. This class fully supports reference-only no-copy conversion of the Matrix package dgCMatrix class from R to C++ and vice versa.

WHY: I want read-only no-copy access to a >R Matrix::dgCMatrix in double type in C++, in contrast to RcppArmadillo SpMat and RcppEigen SparseMatrix which are deep copies. I am definitely am not trying to replace the excellent linear algebra and element-wise operations that RcppArmadillo and RcppEigen already offer.

I’m especially shaky on the const_iterator syntax. Everything works, but may not work as expected (I’m a few months new to C++/Rcpp).

This is pretty bare-bones, but is there any functionality missing that you might expect of a read-only sparse matrix class? I figure the iterator is most important.

RcppSparse.h

#include <rcpp.h>

namespace Rcpp {
    class dgCMatrix {
    public:
        IntegerVector i, p, Dim;
        NumericVector x;
        List Dimnames;

        // constructors
        dgCMatrix(IntegerVector& A_i, IntegerVector& A_p, NumericVector& A_x, int nrow) {
            i = A_i;
            p = A_p;
            x = A_x;
            Dim = IntegerVector::create(nrow, A_p.size() - 1);
        };
        dgCMatrix(IntegerVector& A_i, IntegerVector& A_p, NumericVector& A_x, int nrow, List& A_Dimnames) {
            i = A_i;
            p = A_p;
            x = A_x;
            Dim = IntegerVector::create(nrow, A_p.size() - 1);
            Dimnames = A_Dimnames;
        };
        dgCMatrix(S4 mat) {
            i = mat.slot("i");
            p = mat.slot("p");
            x = mat.slot("x");
            Dim = mat.slot("Dim");
            Dimnames = mat.slot("Dimnames");
        };

        // basic properties
        int nrow() { return Dim(0); };
        int ncol() { return Dim(1); };
        int rows() { return Dim(0); };
        int cols() { return Dim(1); };
        int n_nonzero() { return x.size(); };
        NumericVector& nonzeros() { return x; };
        double sum() { return Rcpp::sum(x); };

        // forward constant iterator
        class const_iterator {
        public:
            int index;
            const_iterator(dgCMatrix& g, int ind) : parent(g) { index = ind; }
            bool operator!=(const_iterator x) const { return index != x.index; };
            bool operator==(const_iterator x) const { return index == x.index; };
            bool operator<(const_iterator x) const { return index < x.index; };
            bool operator>(const_iterator x) const { return index > x.index; };
            const_iterator& operator++(int) { ++index; return (*this); };
            const_iterator& operator--(int) { --index; return (*this); };
            int row() { return parent.i(index); };
            int col() { int j = 0; for (; j < parent.p.size(); ++j) if (parent.p(j) >= index) break; return j; };
            double& operator*() { return parent.x(index); };
        private:
            dgCMatrix& parent;
        };

        // iterator constructors
        const_iterator begin(int j) { return const_iterator(*this, (int)0); };
        const_iterator end(int j) { return const_iterator(*this, i.size() - 1); };
        const_iterator begin_col(int j) { return const_iterator(*this, p(j)); };
        const_iterator end_col(int j) { return const_iterator(*this, p(j + 1)); };

        // read-only element access
        double at(int row, int col) const {
            for (int j = p(col); j < p(col + 1); ++j) {
                if (i(j) == row) return x(j);
                else if (i(j) > row) break;
            }
            return 0.0;
        }
        double operator()(int row, int col) { return at(row, col); };
        NumericVector operator()(int row, IntegerVector& col) {
            NumericVector res(col.size());
            for (int j = 0; j < col.size(); ++j) res(j) = at(row, col(j));
            return res;
        };
        NumericVector operator()(IntegerVector& row, int col) {
            NumericVector res(row.size());
            for (int j = 0; j < row.size(); ++j) res(j) = at(row(j), col);
            return res;
        };
        NumericMatrix operator()(IntegerVector& row, IntegerVector& col) {
            NumericMatrix res(row.size(), col.size());
            for (int j = 0; j < row.size(); ++j)
                for (int k = 0; k < col.size(); ++k)
                    res(j, k) = at(row(j), col(k));
            return res;
        };

        // column access (copy)
        NumericVector col(int col) {
            NumericVector c(Dim(0), 0.0);
            for (int j = p(col); j < p(col + 1); ++j)
                c(i(j)) = x(j);
            return c;
        }
        NumericVector column(int c) { return col(c); }
        NumericMatrix cols(IntegerVector& c) {
            NumericMatrix res(Dim(0), c.size());
            for (int j = 0; j < c.size(); ++j) {
                res.column(j) = col(c(j));
            }
            return res;
        }
        NumericMatrix columns(IntegerVector& c) { return cols(c); }

        // row access (copy)
        NumericVector row(int row) {
            NumericVector r(Dim(1), 0.0);
            for (int col = 0; col < Dim(1); ++col) {
                for (int j = p(col); j < p(col + 1); ++j) {
                    if (i(j) == row) r(col) = x(j);
                    else if (i(j) > row) break;
                }
            }
            return r;
        }
        NumericMatrix rows(IntegerVector& r) {
            NumericMatrix res(r.size(), Dim(1));
            for (int j = 0; j < r.size(); ++j) {
                res.row(j) = row(r(j));
            }
            return res;
        }

        // colSums and rowSums family
        NumericVector colSums() {
            NumericVector sums(Dim(1));
            for (int col = 0; col < Dim(1); ++col)
                for (int j = p(col); j < p(col + 1); ++j)
                    sums(col) += x(j);
            return sums;
        }
        NumericVector rowSums() {
            NumericVector sums(Dim(0));
            for (int col = 0; col < Dim(1); ++col)
                for (int j = p(col); j < p(col + 1); ++j)
                    sums(i(j)) += x(j);
            return sums;
        }
        NumericVector colMeans() {
            NumericVector sums = colSums();
            for (int i = 0; i < sums.size(); ++i) sums(i) = sums(i) / Dim(0);
            return sums;
        };
        NumericVector rowMeans() {
            NumericVector sums = rowSums();
            for (int i = 0; i < sums.size(); ++i) sums(i) = sums(i) / Dim(1);
            return sums;
        };
    };

    // Rcpp::as
    template <> dgCMatrix as(SEXP mat) { return dgCMatrix(mat); }

    // Rcpp::wrap
    template <> SEXP wrap(const dgCMatrix& sm) {
        S4 s(std::string("dgCMatrix"));
        s.slot("i") = sm.i;
        s.slot("p") = sm.p;
        s.slot("x") = sm.x;
        s.slot("Dim") = sm.Dim;
        s.slot("Dimnames") = sm.Dimnames;
        return s;
    }
}

EXAMPLE USAGE:

In C++:

#include <RcppSparse.h>
// ((Rcpp::export))
Rcpp::NumericVector Rcpp_colSums(Rcpp::dgCMatrix& mat){
     return mat.colSums();
}

In R:

library(Matrix)
mat <- rsparsematrix(100, 100, 0.5)
colSums <- Rcpp_colSums(mat)

dnd 5e – Does “Changing a skill” of Tasha allows me to changing a skill proficiency from the background for one offered by the class?

It’s up to the DM, but the language does not contain an explicit restriction.

This section is actually quite short:

Sometimes you pick a skill proficiency that ends up not being very useful in the campaign or that no longer fits your character’s story. In those cases, talk to your DM about replacing that skill proficiency with another skill proficiency offered by your class at 1st level.

That this is entirely up to the DM is hard coded into this rule. That said, the language does not contain any restriction on which skills may be replaced, it simply says “sometimes you pick a skill”.

So this isn’t like an ability score improvement where I just pick what I want. I don’t have to talk to my DM when making a decision about an ability score improvement. Working with your DM on this is just part of the process.

Personally, I see no reason whatsoever to not allow you to change any skill proficiency you want. But your DM may see a reason, and that is okay too.

dnd 5e – Did “Changing a skill” of Tasha allows me to changing a skill proficiency from the background for one offered by the class?

I was arguing with my DM that it works. But he don’t think so. Actually it seems to me there’s no restriction of the origin of a skill proficiency to it can be changed. I’ve understood from the rule that as long as you have a skill proficiency, you can change it if your DM accept. And he understood that if you can only replace it by one offered by your class it has necessarily to had been got from your class.

filters – remove_action: how to access to a method in an child class?

You can’t. Not how you’ve written it. You need to be able to access the instance of ChildAdminClass somehow, but it only exists within the MainAdminClass class and isn’t exposed in any way.

In your code attempting to remove it you’ve referenced $child_admin as a global variable, but you didn’t create it as a global variable. If you did this:

public function init() {
    global $child_admin;

    $child_admin = new ChildAdminClass();
    $child_admin->init();
}

Now this would work:

global $child_admin;
remove_action('admin_notices', array($child_admin, 'printFoo'));

But global variables aren’t great. A better way to do this might be to store a reference to the instance of the child class as property on the main class:

class MainAdminClass {
    public $child_admin;

    public function init() {
        $this->child_admin = new ChildAdminClass();
        $this->child_admin->init();
    }
}

If you do it that way you can remove it like this:

remove_action('admin_notices', array($main_admin_class->child_admin, 'printFoo'));

That’s assuming that $main_admin_class is available in whichever scope you’re using this code in. This gets to the main issue: To remove an action from a class instance, you need to pass that exact instance. So this all comes down to variable scope and making sure that the class instances are accessible so that they can be used to remove hooks. Ultimately that’s a pure PHP issue, rather than anything specific to WordPress.

java – Architectural problem for class combination (cartesian product) for save format strategy

Hello to everyone and thank you for any suggestion.

I have a family of subclasses of Track (Track is abstract).
Every concrete Track has a different number and types of fields (attributes) that extend the basic abstract track-fields.

Then I have a family of file-types that implement some methods (saveRow() etc..).
Every file is presumed to have different type of row-formatting (imagine csv tabs, headers etc..)

ex:

  • SimpleTrack: double lat, double lon, Calendar dateTime.
  • DetectionTrack: (as SimpleTrack) + boolean detection.
  • ..
  • CsvFile
  • TxtFile

When I create a new (X)Track and a (Y) file, they are independent by nature, but.. the row is a cartesian product of track & row types.

EDIT
(to be more clear): How can I have many concrete-tracks in one hand and many FileTypes in the other hand, and create well-formatted-rows (differents for every file) by tracks which have different data (columns, headers..)?
es:

  • XtrackRow(double a, double b, Calendar date) -> to -> CVSfile (tab delimited with headers)
  • XtrackRow(double a, double b, Calendar date) -> to -> TXTfile (formatted columns and title)
  • YtrackRow(double a, string, b, int c, double e) -> to CSV ..
  • YtrackRow …. -> to -> docx file (with another kind of table or tabulation)
    ..

I see two kinds of solutions:

  1. Tracks send (right)-formatted row to file: every track has to know which kind of format apply (to rows) to give them to save to any specific type of file.
  2. Tracks send raw-data to any kind of file which is responsible to format them: in this case, the file-class must know wich kind of data has to format (every track has diffrent contents, columns, headers..). Moreover, every track-class has to send different number and types of parameter..

The second solution seems to be more fitted to the Single-Responsibility principle.. but I have no Idea how to implement it.

I tried to use Bridge Pattern to solve this problem (using first solution):

abstract class Track{
  ...
  FileInterface file;

  Track(FileInterface fileType){
    this.file = fileType;
  }

  abstract String formatConcreteTrackRow();
  
  void sendRow(){
    String rowToSave = formatConcreteTrackRow();
    file.saveRow(rowToSave);
  }
}

By this way the problem is not already solved, because every concrete-track has to implement a set of methods which returs right formatted rowString: one for every file-type.
If I use a Strategy Pattern:

class SimpleTrack extends Track{
  ...
  RowFormatStrategy rowStrategy;
  
  @override
  String formatConcreteTrackRow(){
    return this.rowStrategy.getRowString("args")
}

but in this case.. every concrete-track require a different StrategyInterface, because every concrete-track has different number and types of arguments to elaborate..
If I do not use Strategy Pattern and I define a set of methods (formatCsvRow(args),formatTxtRow(args)..) I need to include a switch(fileType) loop to choose which method to use.. breaking SOLID principles.. 🙁

Moreover..
how to impose, for every new concrete-track to have right row-format methods for every existent file-template-row?
and.. How to impose, at the same time, for every new file-class to impose new templates and relative methods in every existent concrete-track?

To be honest, it’s also quite reductive impose formatConcreteTrackRow to be a String, but it’s over and over the main problem.

I’m not interested to maintain this kind of class structure, this is only the best solution I found trying to follow SOLID principles. If you can show me a better solution, my intent is to study and understand SOLID procedures to solve these kind of purposes.

(I looked around for similar questions, but I’m not even able to define the specific problem itself..)
Thank you very much.