G
G
germn2012-05-10 06:57:42
PHP
germn, 2012-05-10 06:57:42

How to separate class declaration from its implementation in php?

I apologize in advance if this is a stupid question, I googled for a long time, but did not find an answer.
Let's say we have a DataKeeper class:

class DataKeeper {
  private $data;

  public function setData($data) {
    // реализация
  }
  public function getData() {
    // реализация
  }
  public function saveData() {
    // реализация
  }
  private function processData() {
    // реализация
  }
}

The user of the class does not need to know exactly how the functions work. It is enough for him to know only about the presence of open functions with which he can work.
I want to put the disclosure of the implementation details of the class into a separate file, and in the “main” have something like:
class DataKeeper {
  public function getData()
  public function setData($data)
  public function saveData()
}

How to do it?
Upd:
Thanks for the answers about interfaces. I'm probably dumb, but I don't think this is a solution to the problem.
Live example:
Let's say I have a DataKeeper.php file. It declares the DataKeeper interface.
It is implemented by the FileDataKeeper class (saves data to a file) located in its file. It turns out that in the project, I will still have to write: In the DataKeeper.php file (and only it, in theory, we should look at) there is not a word about FileDataKeeper. In addition, if I want to change the storage implementation by replacing the FileDataKeeper class, for example, with MySQLDataKeeper, the interface and public methods will not change, but the “new FileDataKeeper” will need to be changed throughout the project.
class FileDataKeeper implements DataKeeper
$dk = new FileDataKeeper;

Answer the question

In order to leave comments, you need to log in

13 answer(s)
S
Skpd, 2012-05-10
@germn

interfaces.

class DataKeeper implements IDataKeeper {
  private $data;

  public function setData($data) {
    // реализация
  }
  public function getData() {
    // реализация
  }
  public function saveData() {
    // реализация
  }
  private function processData() {
    // реализация
  }
}

interface IDataKeeper {
    public function getData();
    public function setData($data);
    public function saveData();
}

E
evilbloodydemon, 2012-05-10
@evilbloodydemon

In addition, if I want to change the storage implementation by replacing the FileDataKeeper class, for example, with MySQLDataKeeper, the interface and public methods will not change, but the “new FileDataKeeper” will need to be changed throughout the project.

en.wikipedia.org/wiki/Dependency_injection

D
deadkrolik, 2012-05-10
@deadkrolik

Interfaces?

P
patashnik, 2012-05-10
@patashnik

This is the beauty of interfaces, then in the code FileDataKeeper will be used only when creating an object, and the object itself will be passed by the DataKeeper type, i.e.

$keeper = new FileDataKeeper();
$someService->setDataKeeper($keeper);
// or 
$keeper = new MysqlDataKeeper();
$someService->setDataKeeper($keeper);

class SomeService
{
    // ...
    public function setDataKeeper(DataKeeper $keeper)
    {
         // ...
    }
    // ...
}

Z
zhulan0v, 2012-05-10
@zhulan0v

You can use the DataKeeper class in the code, which inside itself determines, for example, based on the application config, which specific driver to use - FileDataKeeper or MySQLDataKeeper.
In this case, the transition from one driver to another will be transparent for the application.
In general, read about design patterns.

B
balloon, 2012-05-10
@balloon

It seems to me that:
1. As a result, you will come to an abstract class
2. All the same, you will have to create a dependency container if you do not want the parent class to know about the heirs.

abstract class DataKeeper {
  protected $data;

  public function setData($data) {
    $this->data = $data;
  }

  public function getData() {
    return $this->data;
  }

  abstract public function save()
  
  abstract public function process()
}

class FileDataKeeper extend DataKeeper {

  public function save() {
    // implementation
  }

  public function process() {
    // implementation
  }
}

class Container {
  protected static $classes = array();  

  public static function register($alias, $class) {
    self::$classes[$alias] = $class;    
  }

  public static function get($alias) {
    if (!isset(self::$classes[$alias]))
  throw new Exception("...");      

    $className = self::$classes[$alias];
    return new $className();
  }
}


// bootstrap.php
Container:register("dataKeeper", "FileDataKeeper");

// SomeWhere.php
$dataKeeper = Container::get("dataKeeper");

N
Nikolai Vasilchuk, 2012-05-10
@Anonym

If it is needed, for informational purposes only, it is better to use phpDoc. Well, or, as advised above, an interface, but then the class name and interface name will be different (as I understand it, not exactly what you need).

R
Renat Ibragimov, 2012-05-10
@MpaK999

interface, abstract
and in order not to specify the name of the class in your case, then read about Factories.

G
Gleb Starkov, 2012-05-10
@colonel

What problem are you solving exactly?
What is the purpose of such a class implementation?

I
Ilya Plotnikov, 2012-05-10
@ilyaplot

Change the structure of your code. Or make a class that combines all storage methods.
$dkm = new DataKeeper("mysql");
$dkf = new DataKeeper("file");

S
shagguboy, 2012-05-10
@shagguboy

> It turns out that in the project, I still need to write:
> $ dk = new FileDataKeeper;
Autoload?

A
Alexey Zakharov, 2014-12-30
@Zakhar0v

// в зависимости от конфига или какого нибудь условия $storageMethod = 'имя класса'
$dk = new  $storageMethod;

Or I just don't understand the question...

K
kambur, 2014-06-03
@kambur

You are all rightly advised, but you need to combine everything:
1. To hide the implementation of a class, you need to use interfaces.
2. As for $dk = new FileDataKeeper; - then the solution to this problem is the Factory. You create another Factory class with a method, say getStorrage(); For each storage option you will have a class (FileDataKeeper, MySQLDataKeeper...). We get:
$dk = Factory::getStorage();
But getStorage() will analyze the situation and return either new FileDataKeeper() or new MySQLDataKeeper() plus its implementation will also be closed.
As a result, we give the user information about the interface (available methods) and a method for obtaining the storage class.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question