I am learning OOP and SOLID. I have a 'main' class that performs some actions after reading variables from a config file. This 'main' class is not the focus of this question but it can be described as a concretion.
I am trying to split up the process of reading the config file and using its settings in the 'main' class.
I am thinking of making a Config
class.
interface ConfigInterface {
public function getFileContents();
}
class Config implements ConfigInterface {
protected $file_path;
protected $file_contents;
public function getFileContents() {
return $this->file_contents;
}
protected function readFileContents() {
$file_path = $this->file_path;
if ( is_file( $file_path ) ) {
$file_contents = include( $file_path );
return $file_contents;
} else {
die( 'Invalid config path specified ' . $file_path );
}
}
public function __construct( $file_path ) {
$this->file_path = realpath( $file_path );
$this->file_contents = $this->readFileContents();
}
}
This allows a user to get all the settings as a single array from the public method.
However, as a class, I can't help but feel these settings retrieved as an array should be assigned as individual properties of the object with public accessors. As such, these settings would be unique to my 'main' class. In this case, I'm thinking of extending a generic Config
class with a MainConfig
class which would have these specific properties / accessors in relation to my 'main' class.
interface ConfigInterface {
// A config has a path, but doesn't need to have a public interface
// So don't know what goes in here now
}
class Config implements ConfigInterface {
private $file_contents;
public function __construct( $config_path ) {}
protected function readContents() {}
}
class MainConfig extends Config implments ConfigInterface {
private $main_settings_one;
private $main_settings_two;
private $main_settings_three;
public function getMainSettingOne() {};
public function getMainSettingTwo() {};
public function getMainSettingThree() {};
}
Firstly, is this a correct approach or is it better to keep the array? Also, does an interface / base class need functions defined? Or can these be defined later?
Secondly, do I need a ConfigHandler
/ ConfigReader
class? If my 'main' class needs the settings to work, could I just pass the config object to the 'main' class and have a function do this? Or is it a seperate responsibility of another class?
I am also learning coding to an interface. My 'main' class only works with specific settings (is this a concretion?) So if I had
class Main {
public function __construct( ConfigInterface $config ) { // coding to interface
$config->getMainSettingOne(); // specific functionality relating to a concretion?
}
}
$conf = new MainConfig( $path );
$main = new Main( $conf );
If anything but a MainConfig
is passed then my 'main' class will not initialise properly. I was thinking of a 'specialised' interface, for use with my 'main' class.
interface MainConfigInterface {
public function getMainSettingOne();
public function getMainSettingTwo();
public function getMainSettingThree();
}
class Config { ... }
class MainConfig extends Config implments ConfigInterface {
private $main_settings_one;
private $main_settings_two;
private $main_settings_three;
public function getMainSettingOne() {};
public function getMainSettingTwo() {};
public function getMainSettingThree() {};
}
Then back in my 'main' class, I can still code to an interface?
class Main {
public function __construct( MainConfigInterface $config ) { // coding to interface
$config->getMainSettingOne();
}
$conf = new MainConfig( $path );
$main = new Main( $conf );
Finally, is this the correct way to code to an interface in this regard?