* Version 1 - Duplication smell oDoc = CreateObject( "Doctor" ) oDoc.cName = "Cureta" oPatient = CreateObject("LawStudent" ) oPatient.cName = "Ricardo" oDoc.oVocation.Operate( oPatient ) *===================================== Define Class Person As Session cName = "" cSex = "F" dBirth = Date() *-------------------------- Function Age( tdDate As Date ) As Number Return Floor( ( tdDate - this.dBirth ) / 365.25 ) Endfunc Enddefine *===================================== Define Class Professional As Person cTitle = "" lAvailable = .T. oVocation = Null *-------------------------- Function Hire() As Boolean Local llReturn as Boolean llReturn = this.lAvailable If llReturn this.lAvailable = .f. EndIf Return llReturn Endfunc Enddefine *===================================== Define Class Student As Person cUniversity = "" cCareer = "" oVocation = Null Enddefine *===================================== Define Class Vocation As Session cName = "" Enddefine *===================================== Define Class Medicine As Vocation cName = "Medicine" *-------------------------- Function Operate( oPerson As Person ) As Void EndFunc Enddefine *===================================== Define Class Law As Vocation cName = "Law" Enddefine *===================================== Define Class LawStudent As Student *------------------------- Function Init() as Boolean If DoDefault() this.oVocation = CreateObject( "Law" ) EndIf EndFunc Enddefine *===================================== Define Class Lawyer As Professional *------------------------- Function Init() as Boolean If DoDefault() this.oVocation = CreateObject( "Law" ) EndIf EndFunc Enddefine *===================================== Define Class MedicineStudent As Student *------------------------- Function Init() as Boolean If DoDefault() this.oVocation = CreateObject( "Medicine" ) EndIf EndFunc Enddefine *===================================== Define Class Doctor As Professional *------------------------- Function Init() as Boolean If DoDefault() this.oVocation = CreateObject( "Medicine" ) EndIf EndFunc EnddefineFuera de eliminar comentarios (no puedo evitarlo), implementé el método Age para que devuelva la edad y Hire para que contrate a un profesional disponible (al contratarlo deja de estar disponible). Es poco, pero así tenés algo para jugar.
* Version 2 - Duplication eliminated oDoc = CreateObject( "Doctor" ) oDoc.cName = "Cureta" oPatient = CreateObject("LawStudent" ) oPatient.cName = "Ricardo" oDoc.oVocation.Operate( oPatient ) *===================================== Define Class Person As Session cName = "" cSex = "F" dBirth = Date() oVocation = Null *-------------------------- Function Init() as Boolean this.oVocation = this.SetVocation() EndFunc *-------------------------- Function Age( tdDate As Date ) As Number Return Floor( ( tdDate - this.dBirth ) / 365.25 ) EndFunc *-------------------------- Function SetVocation() as Object Return null EndFunc Enddefine *===================================== Define Class Professional As Person cTitle = "" lAvailable = .T. *-------------------------- Function Hire() As Boolean Local llReturn as Boolean llReturn = this.lAvailable If llReturn this.lAvailable = .f. EndIf Return llReturn Endfunc Enddefine *===================================== Define Class Student As Person cUniversity = "" cCareer = "" Enddefine *===================================== Define Class Vocation As Session cName = "" Enddefine *===================================== Define Class Medicine As Vocation cName = "Medicine" *-------------------------- Function Operate( oPerson As Person ) As Void EndFunc Enddefine *===================================== Define Class Law As Vocation cName = "Law" Enddefine *===================================== Define Class LawStudent As Student *-------------------------- Function SetVocation() as Object Return CreateObject( "Law" ) EndFunc Enddefine *===================================== Define Class Lawyer As Professional *-------------------------- Function SetVocation() as Object Return CreateObject( "Law" ) EndFunc Enddefine *===================================== Define Class MedicineStudent As Student *-------------------------- Function SetVocation() as Object Return CreateObject( "Medicine" ) EndFunc Enddefine *===================================== Define Class Doctor As Professional *-------------------------- Function SetVocation() as Object Return CreateObject( "Medicine" ) EndFunc EnddefineEl refactoring utilizado es "Pull Up Method" (subir método; http://www.refactoring.com/catalog/pullUpMethod.html). Notese un detalle: aunque pareciera que en las clases hoja (estudiantes de leyes y medicina, doctor y abogado) estoy reescribiendo el método SetVocation, aquí no hay duplicación, ya que esto es totalmente declarativo. No lo hago con una propiedad para evitar una construcción que es muy Fox-dependiente, pero el criterio sigue siendo el mismo. Tengo un método que debe devolverme la instancia de la vocación que necesito.