Jump to content
php.lv forumi

multiple inheritance


Analgiins
 Share

Recommended Posts

savajadzējās realizēt vienu baigo patternu, ja nemaldos, tad tam keywords ir multiple inheritance. Ir pamata klase A, un ir klases B un C, kas manto klasi A - tātad klase B satur klases A metodes un savas metodes; klase C satur klases A metodes un kaut kādas savas metodes. Šīs visas klases ir abstraktas - viņas nepieciešams pārrakstīt. Ar A klasi jau problēmu nav, bet ir problēmas ar B un C klases pārrakstīšanu, jo cik saprotu, tad tādu lietu kā multiple inheritance PHP neatbalsta. Zemāk ir kods, kā tas viss ir iecerēts, lai strādātu:

 

// Abstraktas klases
abstract class A
{
public function aFunc() {}
}
abstract class B extends A
{
public function bFunc() {}
}
abstract class C extends A
{
public function cFunc() {}
}

// Manas klases, kuras izmantoju darbībā
final class myA extends A
{
// kaut ko pārrakstu
}
final class myB extends B,myA   // šeit protams ir sintakses kļūda (komata dēļ)
{
// kaut ko pārrakstu
}
final class myC extends C,myA   // un arī šeit protams
{
// kaut ko pārrakstu
}

 

Vai ir iespējams izveidot kaut ko tamlīdzīgu, lai varētu izmantot šādi izveidotas klases myA, myB un myC. Maybe ar interfeisu implementēšanu kaut ko tādu var panākt? Plzz help :(

 

Edit: varbūt ar kaut kādām "factory" metodēm ko līdzīgu var panākt? A maybe ideja vispār nav laba? :)

Edited by Analgiins
Link to comment
Share on other sites

Doma nav laba.. un arī PHP nav multiple-inheritance...

Nafig tev multiple inheritance? Es vēl saprotu to izmantot kaut kur GUI (C++, C#) .. bet PHP... imho, nevajag tādas izvirtības. Var iztikt ar single inheritance:

 

C:Object && I:BaseTable -> C:MyTable

 

 

http://delfins.id.lv/testi/inheritance.php

 

<?php

function mylog($msg)
{
print "$msg<br />";
}

class Object
{
function __construct()
{
	mylog("Object::__construct()");
}
}

interface SysSaveable
{
function save();
}

interface BaseTable
extends SysSaveable
{
function select();
}


class A extends Object
implements BaseTable//, SysSaveable
{
function __construct()
{
	parent::__construct();
	mylog("A::__construct()");
}

function save()
{
	mylog("A::save()");
}

function select()
{
	mylog("A::select()");
}
}

$a = new A();
$a->select();
$a->save();

?>

 

Izskatās, PHP māk multiple `implements` (tas arī loģiski, jo tās ir tikai interfaces)... Būtībā pirms kodēt, OOP ir jāizprot un jānovērtē uzdevums un attiecīgi OOP izmantojamību.. vai vajag taisīt `sūdus`, tur kur tos nevajag...

Edited by Delfins
Link to comment
Share on other sites

nu jā, es jau tā arī sapratu, bet kaut ko līdzīgu atradu:

http://www.php.net/manual/en/language.oop5.php#68702

 

Doma jau bija uztaisīt klases DBObject, DBItem, DBList. DBItem atbild par tabulas ierakstu (tātad metodes insert, update, delete, load, fields validating) un DBList atbild par tabulu - tātad sorting, filtering, pagination, bet DBObjevt satur dažas metodes, kas nepieciešamas abām klasēm, piem., setField, getField, fields formatting.

 

Būs vien laikam jātaisa DBObject klasē factory metode, kura atgriezās vajadzīgās (pārrakstītās) klases instanci, bet savukārt DBList un DBItem klases sevī saturēs šo DBObject klases objektu un griezīsies pie viņa apmēram šādi:

 

class myDBItem extends DBItem
{
function __construct()
{
	 // tjip kaut kā tā
	$this->dbobject_driver = 'myDBObject';
	$this->dbobject =& DBObject::factory($this->dbobject_driver);
}

function getField($name)
{
	$this->dbobject->getField($name);
}
}

Link to comment
Share on other sites

Es nesaprotu ko tu gribi panākt ar multiple inheritance... Iedod konkrētu piemēru ar visu koku...

 

Tavā gadījumā viss tāpat, kā manā piemērā.

 

C:DBOBject -> C:DBItem -> C:myDBItem

 

PS: a nafig tev vispār myDBItem? jo par to var atbildēt myDBDriver?

Link to comment
Share on other sites

Nu vajag tāpēc, ka DBObject, DBItem un DBList vajag pārrakstīt (jo ir abstraktas). DBObject ir base klase, DBItem ir extends no DBObject, tāpāt arī DBList ir extends no DBObject. Kā es var nodefinēt jaunos myDBItem un myDBList, ja viņiem jāsatur metodes no arī pārrakstītā myDBObject plus vēl savas "mantotās" metodes no pamata klasēm DBItem un DBList? Piemēru.. nav jau ko iedot, tikai štukoju, ka to visu uztaisīt. Principā jau pirmajā postā ar to piemēru arī parādīju, kādu efektu vēlos panākt.

Tas, ka ir iespējams multi implements, to es zinu, bet kāda jēga no tā, ja es varu "pārdefinēt" interfeicu klasei. Ja DBObject satur 50 metodes, DBList satur savas 30 metodes (tātad viņam kopā jau ir 80), un man vajag pārrakstīt vienu no tājām 50 metodēm DBObject'ā (tātad izveidoju jaunu myDBObjectu) un DBList'ā ar jāpārraksta viena no viņa metodēm. Rezultātā būtu jābūt myDBObject ar vienu pārrakstītu metodi un myDBList ar divām pārrakstītām metodem, jo viņam vajadzētu mantot gan pārrakstīto myDBObject un arī DBList. Nu kaut kā tā, ceru, ka bija saprotams.

Link to comment
Share on other sites

Manuprāt tu esi saputrojies OOP.

1.) Uzzimē Inheritance-Tree

2.) Uzkodē

 

PS: interface ir tikai kā ierobežotājs/piekļuves mehānisms pie implementētām klasēm (to instancēm)

 

Interface gadījums palīdzēs arī pie f-ju parametru definēšanas (PHP5)

 

function doIDBItem_Job_1(IDBItem _dbItem);

Tādejādi restriktējot ieejas/izejas parametrus tikai uz konkrētu tipu/iface (un visām atvasēm)

 

Mans skatījums tavējā kontekstā:

 

CDBObject

CDBItem

IDBItem

-> myDBItem

 

CDBObject

CDBList

IDBList

-> myDBList

Link to comment
Share on other sites

Imho, piekrītu Delfins, ka esi nedaudz saputrojies klasēs. Uz ātro, šiet ir lieki mantot no DBObject - tai vajadzēetu būt pastāvīgai klasei...

Tak, ja reizēm rodas vajadzība pec kaut kā līdzīga "multiple inheritance", var risinat divējādi:

1) veidot mantošanas ķēdīti

abstract class A {
public function Afunction() {}
}
class B extends A {
...
}
class C extends B {
...
}

2) deleģēt funkcijas

class A {
public function Afunction() {}
}
class B {
public function Bfunction() {}
}
class C {
private $a = NULL;
private $b = NULL;

public function __construct() {
	$this->a = new A();
	$this->b = new B();
}
public function __call($func,$args) {
	if(method_exists($this->a,$func) {
		$this->a->$func($args);
	}
	elseif(method_exists($this->b,$func) {
		$this->b->$func($args);
	}
	else {
		throw new Exception('Undefined method "'.$func.'" called');
	}
}
}

Link to comment
Share on other sites

Tavs 2. variants ir korekts, bet neerts :)

Parasti to tā arī izmanto :)

 

$item->a()->do_A_Something();

 

PS: vismaz PHP5 jau to ļauj izmantot

PPS: protams, ka a() jāpadod pointers (bet PHP5 laikam defaultā handlo šitā)

Link to comment
Share on other sites

 Share

×
×
  • Create New...