接口,抽象,编码到接口

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? 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?