/    Sign up×
Community /Pin to ProfileBookmark

re:morfing classes.

I found this solution to be a tough one, but it needs tweaking.

Imagine, there is a class clsUSERtraining which extends a base class clsUSERmanual. There are many instances of clsUSERtraining each corresponding to a section in the training manual. There are a few training manuals. It is easy to instantiate any of the sections in a training manual morfing into class clsUSERtraining, so the code can remain
$aSECTION = new clsUSERtraining () ; Not a problem. That training manual data is in an ISAM database, and not in a transactional database.

However when Tom Sawyer signs up for a portfolio, he has to complete two training manuals, before given the post(not a terrorist post by any means). Tom Sawyer starts as an apprentice. My php code cannot designate both training manuals to him, in the same php session, because classes cannot remorf.

My solution is to get the job done the next time Tom accesses his data, which could be a simple button confirm click – did you enjoy that?

Before the tentative solution, my idea was to get php to trash its parser and give me a new parser mid-stream, so the needed class can remorf! This is only needed once at signup, because I had to copy its adjacent InfoCenter class to another name so they could run side-by-side.

Any ideas?

to post a comment
PHP

10 Comments(s)

Copy linkTweet thisAlerts:
@eval_BadCode_Feb 15.2012 — I see two things that I can't guarantee you is the source of your problem, but I get the feeling it is the entire problem. Ill fire off the points really quickly so I don't get lost myself:

  • 1. You failed the is_a test horribly.


  • 2. Morphing the "if". You are trying to overload you classes with inappropriate things (things that do not belong in the user class). You are making your user class do TOO much, that is why it is hard to extend and implement it. If the class is doing inappropriate things... (connect to the database, handle redirections, generate manuals etc) you will find that it's impossible to extend because it makes NO sense. Sure it satisfies the "rules of OOP" but it completely fails when you try to use the code and extend it.


  • 3. You are 100% correct that polymorphism is needed here, but there is an "art" to morphing things correctly. This isn't all there is to it, but morphing the "if" out is an interesting place to begin learning how to use polymorphism to your advantage.


  • Basically it's just bad design and here's how I reached that conclusion.

    extending && "is a" test:

    A user is [B][U]not[/U][/B] a training manual. If you extend something, the rule of thumb is that:

    class Hawk extends Bird {}

    [U]Is a[/U] Hawk a Bird. Yes! That makes sense. As long as Bird has been written in a decent way and is not "final".

    class Tornado extends Truck {}

    [U]Is a[/U] Tornado a Truck? No. The rules of OOP allow this to happen, but it incredibly terrible design. There's just no way to reasonably say that a Tornado is a Truck. But Tornado would be carrying that type information around with it, if I tested it

    var_dump(new Tornado() instance_of Truck);

    Yeah it's a truck. But it isn't... RAGE!!!!!!!!!!! :mad:



    Take this with a grain of salt, but I think it should look more like this:
    [code=php]
    abstract class AbstractUser {
    abstract private function authenticate();
    abstract private function authorize($username);
    abstract function getEmail();
    abstract function getUserName();
    abstract function getIdentity();

    }

    /*
    write abstract functions that MUST be implemented to force
    classes extending this to be abstract or implement the function.
    If something extending AbstractUser is a User, then it should be
    able to implement these functions. If it can't implement these
    functions, then User is defined incorrectly, or you are trying to
    make something a User that isn't.
    */

    abstract class LoginUser extends AbstractUser {

    final private function authenticate() { ... }
    final private function authorize($username) { ... }

    final function getIdentity() {
    //get the identity (int/primary key) from the database that is used to identify the user.
    return (int) $identity;
    }

    }

    class SiteUser extends LoginUser {
    public function setCurrentManual(Manual $manual) { ... }
    public function getCompletedManuals() { ... }
    public function markManualAsCompleted(Manual $manual) { ... }
    public abstract function requiresTraining();
    }

    abstract class UserInTraining extends SiteUser {
    public function getNextRequiredManual() { ... }
    final public function requiresTraining() { return true; }
    }

    class UserNotInTraining extends SiteUser {
    public function postToBoards() { ... } //maybe only users who have completed training can post to the forums etc.
    public function requiresTraining() { return false; }
    }

    abstract class Manual { ... (lots of manual stuff here) ...
    abstract function isRequired(); //morph the "if" out.
    }

    class RequiredManual extends Manual {
    final public function isRequired() { return true; }
    }
    class OptionalManual extends Manual {
    final public function isRequired() { return false; }
    }

    [/code]


    Unfortunately I'm not sure if I can show you. I tried my best to explain polymorphism, but it's one of those things that must "click". I can explain it 100 times and you could still not see it. It's all about dispatching the correct method. You do know you can overwrite methods that aren't declared [U]final[/U] right?

    Edit: Don't take the criticism personally. I made all the same mistakes multiple times.
    Copy linkTweet thisAlerts:
    @WyCnetauthorFeb 15.2012 — You are explaining too much basic work. The problem iis a PHP parsing problem. I take advantage of the interpretative nature of PHP.

    The extension of the base class is basically information for the methods to manipulate. Because of its modular nature the methods do not care which section the user is learning. If I have thirteen sections of information, then the database only needs to inform about a section number, then string processing takes place and clsUSERtraining is available in minimum form., [B]as a dynamic creation.[/B]

    Morfing the class is a string processing trick of the high teck trade. So after producing a minimum footprint for clsUSERtraining, in the next step,PHP refuses to budge, that is it will not allow me to redefine my class, so I cannot achieve ultimate reusability.

    Asking for a clean slate is an old trick in interpretative parsing, if you know what I mean!
    Copy linkTweet thisAlerts:
    @eval_BadCode_Feb 15.2012 — I think you mean "hack" and not "polymorphism". I have an eval hack that lets you implement dynamic interfaces- perhaps working around the rules of PHP-OOP is what you are looking for?

    I would do better with real code, as I am not following your problem. Please provide more information/example code. :p This sounds interesting, hope to hear back from you.

    Edit: let me stress that dynamically implementing interfaces is a big NO! I would be so annoyed if anyone actually did this in a system I'm working on. But basically, PHP will interpret the string "that is" a class definition inside of eval(). This allows you to break ...... basically, every standard of OOP. In some very rare circumstances this might be OK. I think a few complex combinatorial problems would fall into this category.
    Copy linkTweet thisAlerts:
    @NogDogFeb 15.2012 — ...if you know what I mean![/QUOTE]

    Nope, not really. I read the original post soon after it was first posted, and didn't understand what the problem was nor what you were trying to do. Re-reading it now, I still don't. ? Either you're into something way over my head, or it's just a language issue keeping me from understanding something that's actually simpler than it appears. ? )

    But, purely a guess that may be way off target (see above), I might suggest that UserTraining should not be a child of UserManual. Instead, UserTraining should be a separate class whose objects can contain one or more UserManual objects (added as the user "qualifies" for them).

    If you truly feel that UserTraining "is a" UserManual, then it might be possible to model it that way using the Composite pattern* to still allow a UserTraining object to contain n UserManual objects.

    ___________
  • * Not claiming that's the best link to learn about this pattern, just the first one Google showed me that looked reasonable.
  • Copy linkTweet thisAlerts:
    @WyCnetauthorFeb 15.2012 — Excuse me, there are cautions listed concerning proper examples on this.site that I neglected to follow.

    Look at CauseGroup it holds data for er,um, an Expert system, and browser JS support. I have a few files each file containing a section in the training manual, each called (you may disagree) CauseGroup extending the same ActionBase.



    <?php

    class CauseGroup extends ActionBase {

    // Option should be the exchange - axia name

    var $CauseGroupAxes = array ('known type',

    'html','java','java parameters','photo',

    'prompt','option','selected',

    'option true', 'option false'

    ) ;

    var $Data0 =

    array ('Multiple Choice','WyCmc.php',

    'jrSALESindex.php',

    'WyCProducts.js','startPHOTOclientBG', 'webpics/THFL03.JPG',

    'ypcloud-bb4.JPG','ypcloud-bb3.JPG', 'A Sales (Rep) Submission to WyCNet', '27',

    'X','webpics/WyCoffOL2.JPG','webpics/WyConOL.JPG',

    ' Choose it ',' - Change Selection - ',

    'webpics/WyCmc1.JPG','ypcloud-bb3.JPG',

    'WyClogo.JPG','WyCmc.JPG') ;

    var $Meta0 = array (2,1,7,7,2);

    var $Distinct0 = array ('known type','html','java','java parameters','photo') ;

    var $Type0 = 'Multiple Choice' ;

    // CauseGroup has more information...

    }

    ?>

    [/quote]


    Here is how it is instantiated.


    <?php

    include_once ("WyCapprenticeAB.php") ;

    [B]include_once ($CauseGroup."C.php");[/B]

    class ApprenticeCauses extends Apprentice {

    var $Name ;

    var $Causes = WyCList ;

    var $aKnownType ;

    function __construct ($goalNAME,$groupNAME){

    // need to look up $groupNAME ;

    [B]$GG = new CauseGroup($groupNAME)[/B] ;

    $this->Causes = new WyCList () ;

    $this->Causes->ListAddArray [B]($GG->CauseGroupAxes) ;[/B]

    $this->gTransitions = new WyCList() ;

    $this->gTransitions->ListClone([B]$GG->Transition)[/B] ;

    $this->Name = $goalNAME ; $Ns = [B]$GG->EveStates[/B] ;

    $this->loopSIZE($groupNAME,[B]$Ns[/B]) ;

    [B]$this->AddGroup($GG)[/B] ;

    [B]unset[/B] ($GG) ;

    $this->Causes->ListTop() ;

    }

    // more follows

    }
    [/quote]


    The class loads and is available with the correct training section and no extra memory overhead, as it slogs through its server side heuristics.

    After one round from JrSales, CauseGroup is immutable and cannot be used again for the session, so a CauseGroup from the busking manual, cannot execute.
    Copy linkTweet thisAlerts:
    @eval_BadCode_Feb 16.2012 — PHP doesn't support two class definitions with the same class name at the same time. Let me stress that this is not a problem with the parser. This behaviour was intended.

    Edit:

    You can perhaps do this with namespaces:

    What are namespaces? In the broadest definition namespaces are a way of encapsulating items. This can be seen as an abstract concept in many places. For example, in any operating system directories serve to group related files, and act as a namespace for the files within them. As a concrete example, the file foo.txt can exist in both directory /home/greg and in /home/other, but two copies of foo.txt cannot co-exist in the same directory. In addition, to access the foo.txt file outside of the /home/greg directory, we must prepend the directory name to the file name using the directory separator to get /home/greg/foo.txt. This same principle extends to namespaces in the programming world.
    [/QUOTE]

    src: http://php.net/namespaces
    Copy linkTweet thisAlerts:
    @ssystemsFeb 16.2012 — Nope, not really. I read the original post soon after it was first posted, and didn't understand what the problem was nor what you were trying to do. Re-reading it now, I still don't. ? [/QUOTE]

    I second that

    PHP doesn't support two class definitions with the same class name at the same time.[/QUOTE]

    Not only in PHP.
    Copy linkTweet thisAlerts:
    @WyCnetauthorFeb 17.2012 — What purpose would people think the variable [I][B]$CauseGroup[/B][/I] assists to achieve? Simply put, $CauseGroup, has the section name, of the training manual, cantaining the [B]class CauseGroup extends ActionBase {}.[/B]

    Ten sections correspond to having "CauseGroupX.php", where X ranges from 1..10.

    Think of what the alternative would be?


    <?php

    include_once ("WyCapprenticeAB.php") ;

    [B]include_once ($CauseGroup."C.php");[/B]

    class ApprenticeCauses extends Apprentice {

    var $Name

    // the other parts fit here...

    ?>
    [/quote]
    Copy linkTweet thisAlerts:
    @eval_BadCode_Feb 18.2012 — :eek::eek:?:eek:?:eek:?

    What have I done?
    Copy linkTweet thisAlerts:
    @WyCnetauthorFeb 18.2012 — Using static classes with possible giant footprint, and enormous class construction time:

    (A) Here is the normal psuedo-flow.

    (1) Server gets request for PHP action.

    (2) PHP fetches needed information in static pre-concieved files that store classes ect. The total footprint is largest in this scenario.

    (3) Scripts run and returns information to browser.
    [/quote]


    Using dynamic classes(morfed) with absolutely minimum footprint, and minimal class construction time, for non Mickey Mouse and Minnie Mouse applicatins:

    (? Here is the WyCnet altered PART(A) psuedo-flow.

    (1) Server gets request for PHP action.

    (2a) PHP fetches needed information in static pre-concieved files that does string processing for a dynamic class, and in so doing minimizes footprint.

    (2b) PHP fetches needed information to support dynamically scripted classes ect (be very careful here, the script can crash iff not well thought over).

    (3) Scripts run and returns information to browser.
    [/quote]


    p.s.

    I remember some time ago an expert OS collegue of mine telling me, "never mess with the (VMS) execution stack, you cannot succeed.".

    Well, I did, and I did, and it was well done, and all were well pleased!
    ×

    Success!

    Help @WyCnet spread the word by sharing this article on Twitter...

    Tweet This
    Sign in
    Forgot password?
    Sign in with TwitchSign in with GithubCreate Account
    about: ({
    version: 0.1.9 BETA 5.27,
    whats_new: community page,
    up_next: more Davinci•003 tasks,
    coming_soon: events calendar,
    social: @webDeveloperHQ
    });

    legal: ({
    terms: of use,
    privacy: policy
    });
    changelog: (
    version: 0.1.9,
    notes: added community page

    version: 0.1.8,
    notes: added Davinci•003

    version: 0.1.7,
    notes: upvote answers to bounties

    version: 0.1.6,
    notes: article editor refresh
    )...
    recent_tips: (
    tipper: @AriseFacilitySolutions09,
    tipped: article
    amount: 1000 SATS,

    tipper: @Yussuf4331,
    tipped: article
    amount: 1000 SATS,

    tipper: @darkwebsites540,
    tipped: article
    amount: 10 SATS,
    )...