Página 1 de 1
Super:Super:AlgumaCoisa()
Enviado: 16 Set 2013 18:03
por JoséQuintas
Tem isso no Harbour?
Tem como escolher uma das classes herdadas superiores através de super:super ou super: ?
(escolher entre roitna da classe herdada, ou rotina que a classe herdada havia herdado de outra)
Obs. Acho que cheguei no nível 5 de herança, e precisava algo da classe do nível 4.
Super:Super:AlgumaCoisa()
Enviado: 16 Set 2013 18:24
por JoséQuintas
Não, não é pra complicar, é pra facilitar.
Por enquanto meu cadastro de mídia está assim:
Código: Selecionar todos
PROCEDURE PAUXMIDIA
LOCAL oFrm := AUXMIDIAClass():New()
IF .NOT. AbreArquivos( { "jptabel" } )
RETURN
ENDIF
SELECT jptabel
SET FILTER TO jptabel->axTabela == "MIDIA."
oFrm:Execute()
CLOSE DATABASES
RETURN
CREATE CLASS AUXMIDIAClass INHERIT AUXILIARClass
DATA cTabelaAuxiliar INIT "MIDIA."
END CLASS
E alguns outros cadastros genéricos estão parecidos.
Mas este, assim como outros cadastros já receberam, vai receber um método Exclui() próprio, pra verificar se o código está sendo usado antes de excluir.
Pelo menos na parte final é chamar o Super;Exclui() que pega o Exclui() da classe principal, que só pede confirmação e exclui o registro atual.
Mas se precisar de um método da classe intermediária, como fazer?
Super:Super:AlgumaCoisa()
Enviado: 16 Set 2013 18:27
por JoséQuintas
A classe que foi herdada pelo anterior é esta:
Código: Selecionar todos
CREATE CLASS AUXILIARClass INHERIT FrmCadastroClass
DATA cTabelaAuxiliar INIT "NAOTEM"
METHOD Especifico( lExiste )
METHOD TelaDados( lDigita )
METHOD Valida( cCodigo, lShow )
METHOD GridSelection()
END CLASS
METHOD GridSelection() CLASS AUXILIARClass
LOCAL oTBrowse, nSelect := Select(), cOrdSetFocus
oTBrowse := { ;
{ "NOME", "jptabel->axDescri" }, ;
{ "CODIGO", "jptabel->axCodigo" } }
SELECT jptabel
SELECT jptabel
cOrdSetFocus := OrdSetFocus( "descricao" )
FazBrowse( oTBrowse,, ::cTabelaAuxiliar )
IF LastKey() != K_ESC .AND. .NOT. Eof()
KEYBOARD jptabel->axCodigo + Chr( K_ENTER )
ENDIF
OrdSetFocus( cOrdSetFocus )
SELECT ( nSelect )
RETURN NIL
METHOD Especifico( lExiste ) CLASS AUXILIARClass
LOCAL GetList := {}
LOCAL maxCodigo := jptabel->axCodigo
IF ::cOpc == "I"
maxCodigo := "*NOVO*"
ENDIF
@ Row()+1, 20 GET maxCodigo PICTURE "@K 999999" VALID iif(maxCodigo == "*NOVO*",.t.,vZeros(@maxCodigo) .AND. Val(maxCodigo) > 0 )
Mensagem( "Digite codigo, <F9> pesquisa, <ESC> volta" )
READ
Mensagem()
IF LastKey() == K_ESC .OR. ( Val(maxCodigo) == 0 .AND. maxCodigo != "*NOVO*" )
GOTO ::nUltRec
RETURN .f.
ENDIF
SEEK ::cTabelaAuxiliar + maxCodigo
IF .NOT. ::EspecificoExiste( lExiste, Eof() )
RETURN .f.
ENDIF
::cChave := { maxCodigo }
RETURN .t.
METHOD TelaDados( lDigita ) CLASS AUXILIARClass
LOCAL GetList := {}
LOCAL maxCodigo := jptabel->axCodigo
LOCAL maxDescri := jptabel->axDescri
LOCAL maxInfInc := jptabel->axInfInc
LOCAL maxInfAlt := jptabel->axInfAlt
lDigita := iif( lDigita == NIL, .f., lDigita )
IF lDigita
maxCodigo := ::cChave[1]
::nNumTab := 1
ENDIF
DO WHILE .t.
::ShowTabs()
DO CASE
CASE ::nNumTab == 1
@ Row()+1, 1 SAY "Codigo...........:" GET maxCodigo WHEN .f.
@ Row()+2, 1 SAY "Descricao........:" GET maxDescri PICTURE "@!" VALID .NOT. Empty( maxDescri )
@ Row()+2, 1 SAY "Inf.Inclusao.....:" GET maxInfInc WHEN .f.
@ Row()+1, 1 SAY "Inf.Alteracao....:" GET maxInfAlt WHEN .f.
ENDCASE
IF .NOT. lDigita
CLEAR GETS
EXIT
ENDIF
Mensagem( "Digite campos, <F9> Pesquisa, <ESC> Sai" )
READ
Mensagem()
::nNumTab += 1
IF LastKey() == 27
EXIT
ENDIF
IF ::nNumTab > Len(::acTabName)
EXIT
ENDIF
ENDDO
IF .NOT. lDigita
RETURN NIL
ENDIF
::nNumTab := 1
IF LastKey() == K_ESC
RETURN NIL
ENDIF
IF ::cOpc == "I"
maxCodigo := ::cChave[1]
IF maxCodigo == "*NOVO*"
GOTO BOTTOM
maxCodigo := StrZero( Val( jptabel->axCodigo ) + 1, 6 )
ENDIF
Inclui(.t.)
REPLACE jptabel->axTabela WITH ::cTabelaAuxiliar, jptabel->axCodigo WITH maxCodigo, jptabel->axInfInc WITH LogInfo()
SKIP 0
UNLOCK
ENDIF
Bloqueia(.t.)
REPLACE jptabel->axDescri WITH maxDescri
IF ::cOpc == "A"
REPLACE jptabel->axInfAlt WITH LogInfo()
ENDIF
SKIP 0
UNLOCK
RETURN NIL
METHOD Valida( cCodigo, lShow ) CLASS AUXILIARClass
LOCAL lOk := .t., nRow := Row()
MEMVAR m_Prog
lShow := iif( lShow == NIL, .t., lShow )
IF lShow
@ nRow, 32 SAY EmptyValue( jptabel->axDescri )
ENDIF
cCodigo := StrZero( Val( cCodigo ), 6 )
IF .NOT. Encontra( ::cTabelaAuxiliar + cCodigo, "jptabel", "numlan" )
MsgWarning( "Codigo nao cadastrado!" )
lOk := .f.
ENDIF
IF lShow
@ nRow, 32 SAY jptabel->axDescri
ENDIF
RETURN lOk
Super:Super:AlgumaCoisa()
Enviado: 16 Set 2013 18:41
por JoséQuintas
E essa herda de outra que faz a navegação do cadastro, que herda de outra que faz a parte visual.
Só está separado em classes "por assunto".
Uma classe cuida do visual, outra cuida da navegação do cadastro.
Sobra para o cadastro o que é específico, como liberar acesso conforme senha, validações em geral, telas específicas, etc.
Nesse fonte dá pra eliminar ::nNumTab, já que esse cadastro não precisa de TABS pra multijanelas.
Aliás... esse é o lado ruim de classes: a compilação /w3 /es2 não consegue analisar partes inúteis.
Super:Super:AlgumaCoisa()
Enviado: 16 Set 2013 18:52
por JoséQuintas
Uma outra com algo mais:
Código: Selecionar todos
PROCEDURE PAUXPRODEP
LOCAL oFrm := AUXPRODEPClass():New()
IF .NOT. AbreArquivos( { "jpconfi", "jptabel", "jpitem", "jpnumero", "jpsenha", "jptabel", "jpreguso" } )
RETURN
ENDIF
SELECT jptabel
SET FILTER TO jptabel->axTabela == "PRODEP"
oFrm:Execute()
CLOSE DATABASES
RETURN
CREATE CLASS AUXPRODEPClass INHERIT FrmCadastroClass
DATA cTabelaAuxiliar INIT "PRODEP"
METHOD Intervalo( nLini, nColi, nOpc, mieprodep )
END CLASS
METHOD Intervalo( nLini, nColi, nOpc, mieprodep ) CLASS AUXPRODEPClass
LOCAL acTxtOpc := { "Todos", "Especifico" }
LOCAL GetList := {}
WAchoice( nLini, nColi, acTxtOpc, @nOpc, "Depto de produto" )
IF nOpc == 2
wOpen( nLini, nColi + 10, nLini + 3, nColi + 50, "Depto de produto" )
@ nLini + 2, nColi + 12 GET mieProDep PICTURE "@K 999999" VALID ::Valida( @mieProDep )
Mensagem( "Digite Departamento de Produto, <F9> Pesquisa, <ESC> Sai" )
READ
wClose()
ENDIF
RETURN nOpc
Super:Super:AlgumaCoisa()
Enviado: 02 Out 2013 17:40
por JoséQuintas
Só pra classe intermediária é que não encontrei, mas não sei se é seguro fazer isso.
Pra usar da classe principal é normal, super: funciona.
Classe principal
Código: Selecionar todos
CREATE CLASS CadastroClass
METHOD Exclui()
END CLASS
METHOD Exclui CLASS CadastroClass
IF MsgYesNo( "Confirma exclusão" )
Bloqueia(.t.)
DELETE
SKIP 0
UNLOCK
ENDIF
RETURN NIL
Classe que recebe herança
Código: Selecionar todos
CREATE CLASSS ProdutoClass INHERIT CadastroClass
METHOD Exclui()
END CLASS
METHOD Exclui() CLASS ProdutoClass
IF produto->Qtde != 0
MsgExclamation( "Não pode excluir produto com saldo" )
RETURN NIL
ENDIF
Super:Exclui()
RETURN NIL
Classe() é a classe.
Classe():New() é o método New() da classe.
Pra passar um parâmetro pro método New(), teria que estar nele. New( 10 )
Deve ser uma das diferenças entre Harbour x xHarbour.
Não sei se poderia ser considerado erro.
Super:Super:AlgumaCoisa()
Enviado: 02 Out 2013 18:09
por JoséQuintas
Fiz um teste aqui:
O New() é a criação da classe, e o Init() a inicialização, não sei se CONSTRUCTOR afeta alguma coisa.
Mas o Init() não recebe parâmetro. Neste exemplo, ::nNumero retorna NIL, porque INIT() foi executado mas não tem parâmetro.
A não ser que alterem, somente o New() que é garantido pra iniciar com valores.
Código: Selecionar todos
#include "hbclass.ch"
PROCEDURE Main
oClasse := TesteClass( 10 ):New()
? oClasse:nNumero
RETURN
CREATE CLASS TesteClass
VAR nNumero INIT 0
METHOD Init( nNumero )
END CLASS
METHOD Init( nNumero ) CLASS TesteClass
::nNumero := nNumero
RETURN NIL
Detalhe curioso: se não iniciar a classe com New(), o método Init() não é executado.
Super:Super:AlgumaCoisa()
Enviado: 03 Nov 2013 05:54
por JoséQuintas
Sobre classes intermediárias.
Encontrei a resposta nos fontes da gtwvg.
Por exemplo, separei a parte de callback da wvgwindow, e chamei de wvgCallback.
E peguei por herança na wvgwindow.
Mas o Destroy() da wvgWindow eliminava as rotinas de Callback.
Pra não duplicar código, coloquei no Destroy() da wvgWindow uma chamada pra ::wvgcallback:Destroy()
Isso permitiu chamar o método específico da classe wvgCallback.
Obs.
Por enquanto só estou tentando entender a wvg. Não tá fácil entender.
Essa separação ajuda por dividir o fonte "por assunto".
E a wvgWindow é a base pra tudo, então o fonte é extenso.