Classes e herança

Projeto [x]Harbour - Compilador de código aberto compatível com o Clipper.

Moderador: Moderadores

Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Classes e herança

Mensagem por JoséQuintas »

Demorei um pouco pra entender a utilidade disso, principalmente herança.
Mas é sensacional.
Só imaginar classe como um conjunto de funções/variáveis, pra executar determinada tarefa.
E herança seria poder modificar uma função da classe, ou adicionar recursos/variáveis, etc.
Vou mostrar um relatório de clientes transformado em classe, e depois usar a herança pra modificar esse mesmo relatório pra imprimir produtos.
É nessa última hora que vemos como a herança é simples mas poderosa.

Este fonte eu fiz tudo num só PRG. Postando aqui em blocos só pra efeito de leitura.

A chamada dos relatórios é igual pra todos

Código: Selecionar todos

#include "hbclass.ch" 
Procedure Main

use jpcadas // clientes
Do Relatorio1
Do Relatorio2
Do Relatorio3
use jpitem // produtos
Do Relatorio4
Close Databases
Return
Primeiro o relatório básico

Código: Selecionar todos

Procedure Relatorio1
Local nLin, nPag

Set Printer To ("lixo1.txt")
Set Device To Print
nLin := 66
nPag := 0
Goto Top
Do While .Not. Eof()
   If nLin > 64
      @ 0, 0 Say "TITULO"
      @ 0, 132-7 Say "Pag." + StrZero(nPag,3)
      @ 1, 0 Say Replicate("-",132)
      nLin := 3
   Endif
   @ nLin, 0 Say jpcadas->cdCodigo
   @ nLin, pCol()+2 Say jpcadas->cdNome
   @ nLin, pCol()+2 Say jpcadas->cdEndereco
   nLin += 1
   Skip
Enddo
Set Printer To
Set Device To Screen
Run ("notepad.exe lixo.txt")
Return
Agora transformado em funções

Código: Selecionar todos

Procedure Relatorio2

cTxtFile := "lixo2.txt"
nLin := 66
nPag := 0
Set Printer To (cTxtFile)
Set Device To Print
Goto Top
Do While .Not. Eof()
   If nLin > 64
      Cabecalho(@nPag,@nLin)
   Endif
   Detalhe(@nLin)
   Skip
Enddo
Set Printer To
Set Device To Screen
ShowRelat(cTxtFile)

Function Cabecalho(nPag,nLin)
nPag += 1
@ 0,0 Say "Titulo"
@ 0,132-7 Say "Pag."+StrZero(nPag,3)
@ 1,0 Say Replicate("-",132)
nLin := 3
Return NIL

Function Detalhe(nLin)
@ nLin, 0 Say jpcadas->cdCodigo
@ nLin, pCol()+2 Say jpcadas->cdNome
@ nLin, pCol()+2 Say jpcadas->cdEndereco
nLin += 1
Return NIL

Function ShowRelat(cTxtFile)
Run ("notepad.exe " + cTxtFile)
Return NIL
Agora transformado em classe
Note que :: se refere a variáveis/funções locais da classe, usava Self: no começo, mas com :: o código fica mais legível.

Código: Selecionar todos

Procedure Relatorio3

Relatorio():Execute("lixo3.txt")
Return NIL

Create Class Relatorio
   Data nLin
   Data nPag
   Data cTxtFile
   Method Cabecalho()
   Method Detalhe()
   Method Execute()
   Method ShowRelat()
   EndClass

Method Cabecalho() Class Relatorio
   ::nPag += 1
   @ 0, 0 Say "Titulo"
   @ 0, 132-7 Say "Pag."+StrZero(::nPag,3)
   @ 1, 0 Say Replicate("-",132)
   ::nLin := 3
   Return NIL
   
Method Detalhe() Class Relatorio
   @ ::nLin, 0 Say jpcadas->cdCodigo
   @ ::nLin, pCol()+2 Say jpcadas->cdNome
   @ ::nLin, pCol()+2 Say jpcadas->cdEndereco
   Return NIL

Method ShowRelat() Class Relatorio
   Run ("notepad.exe " + ::cTxtFile)
   Return NIL

Method Execute(cTxtFile) Class Relatorio
   Set Printer To (cTxtFile)
   Set Device To Print
   ::cTxtFile := cTxtFile
   ::nLin := 66
   ::nPag := 0
   Goto Top
   Do While .Not. Eof()
      If ::nLin > 64
         ::Cabecalho()
      Endif
      ::Detalhe()
      ::nLin += 1
      Skip
   Enddo
   Set Printer To
   Set Device To Screen
   ::ShowRelat()
   Return NIL
Agora o uso da classe com herança usada para produtos ao invés de clientes
Note que a classe nova foi criada a partir da anterior, só foi modificado o método Detalhe(), que é o que interessa modificar.

Código: Selecionar todos

Procedure Relatorio4

RelatorioProduto():Execute("lixo4.txt")

Create Class RelatorioProduto INHERIT Relatorio
   Method Detalhe()
   EndClass
   
Method Detalhe()
   @ 0, 0 Say jpitem->ieItem
   @ 1, pCol()+2 Say jpitem->ieDescri
   Return NIL
A principal vantagem é pegar algo que funcione e modificar somente o que interessa.
A classe de relatório funciona, então alterando só o detalhe vai continuar funcionando.
Notem como o fonte 4 ficou pequeno. É a partir daí que valeu a pena o trabalho.
A mesma classe poder ser usada pra qualquer arquivo, e qualquer layout.

Considerações:
- "#include hbclass.ch" é necessário onde se cria a classe. No fonte que apenas usa classe pronta não é necessário.
- Dentro da criação da classe é necessário colocar os nomes dos métodos
- Nos métodos, necessário colocar o nome da classe a que se refere
- Quando a classe usa alguma variável ou função dela mesma, necessário usar Self:nome ou ::nome
- No caso do último fonte, a classe herda a anterior, então a outra classe precisa estar linqueditada junto.
- Esta classe de relatório é só um simples exemplo. Não serve pra uso normal, porque faltam os títulos das colunas. Mas testei antes de postar, e todos funcionam.

Acaba sendo mais interessante do que ficar usando macros, ou funções que se complicam cada vez mais.
O fonte de classe fica mais organizado e fácil de entender, depois que se pega o jeito.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
ANDRIL
Usuário Nível 5
Usuário Nível 5
Mensagens: 1298
Registrado em: 06 Jul 2004 00:44
Contato:

Classes e herança

Mensagem por ANDRIL »

JoséQuintas escreveu:Demorei um pouco pra entender a utilidade disso, principalmente herança.
Mas é sensacional.
José ótima explicação, simples e direta. Valeu!
Clipper 5.2e / Blinker 5.1 / Harbour 3.2 / GTwvg
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Classes e herança

Mensagem por JoséQuintas »

Faltou só uma coisinha pra completar:
Se na classe "pai de todas" alterar o cabeçalho, já altera todos os relatórios do sistema de uma vez.

Aqui passei a fazer relatórios nesse estilo. Depois fui alterando a classe pra permitir escolher PDF retrato, PDF paisagem e matricial (tem cliente usando). O relatório já se ajusta em linhas/colunas conforme o formato de saída, uma vez que faz uso da classe.
É alterar todos os relatórios de uma vez, só mexendo na classe principal.
Também deixei as opções do menu na classe, sobre os tipos de impressão. Se inventar um PDF de diagonal, é so mexer na classe, e a opção vai aparecer na tela de todos os relatórios.

E pra resolver problemas de impressão.... por exemplo selecionar impressora nos relatórios... só mexer na classe.
Obs. No meu caso, pelo menos por enquanto, só criei uma classe pra relatórios, não precisei subclasse.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
fladimir
Colaborador
Colaborador
Mensagens: 2445
Registrado em: 15 Nov 2006 20:21

Classes e herança

Mensagem por fladimir »

Obrigado colega clareou bastante...

[]´s
Sun Tzu há mais de três mil anos cita nas epígrafes de seu livro “A Arte da Guerra“:

“Concentre-se nos pontos fortes, reconheça as fraquezas, agarre as oportunidades e proteja-se contra as ameaças”.
“Se não é vantajoso, nunca envie suas tropas; se não lhe rende ganhos, nunca utilize seus homens; se não é uma situação perigosa, nunca lute uma batalha precipitada”
.


Até 2017    Desktop Console [ Legado ] Harbour | MinGW | DBF | CDX | FastReport | MySQL


Novos Projetos:

   Desktop Visual           Windev Desktop
   Celular Android/iOS   Windev Mobile
   WEB                            Windev Web


Sejamos gratos a Deus.
alxsts
Colaborador
Colaborador
Mensagens: 3092
Registrado em: 12 Ago 2008 15:50
Localização: São Paulo-SP-Brasil

Classes e herança

Mensagem por alxsts »

Olá!

A OOP, como a maioria das coisas que existem, tem seus prós e contras. Mas, sem dúvida, é uma técnica muito legal mesmo. Dá para fazer coisas sensacionais com ela, inclusive implementar novas funcionalidades nas classes padrão da linguagem e até estender os tipos de dados existentes.

Vejam o código abaixo, extraído do manual do xHarbour(xHarbour Language Reference Guide.chm). Neste exemplo, o tipo de dados Date é estendido, ganhando novos recursos de formatação:

Código: Selecionar todos

// The example implements a class that extends the data type
// Date with advanced date and time formatting capabilities.
// It distinguishes upper and lower case letters for the Day,
// Month and time. A formatting template is built with the
// following characters:
//
// d    - numeric day without leading zero
// dd   - numeric day with leading zero
// ddd  - numeric day without leading zero and postfix (st, nd, rd, th)
// D    - first letter of weekday
// DD   - name of weekday abbreviated to two characters
// DDD  - name of weekday abbreviated to three characters
// DDDD - complete name of weekday
// M    - numeric month without leading zero
// MM   - numeric month with leading zero
// MMM  - month name abbreviated to three letters
// MMMM - complete month name
// yy   - year without century
// yyyy - year with century
// h    - hour without leading zero
// hh   - hour with leading zero
// m    - minute without leading zero
// mm   - minute with leading zero
// s    - second without leading zero
// ss   - second with leading zero
// \    - escape character for d, D, m, M, y, h, m, s

   #include "HbClass.ch"   

   PROCEDURE Main
      LOCAL dDate

      ASSOCIATE CLASS DateFormatter WITH TYPE DATE

      dDate := Ctod( "09/01/2006" )

      ? dDate               
      // result: 09/01/06

      ? dDate:shortDay()
      // result: Fri

      ? dDate:shortMonth()
      // result: Sep

      ? dDate:format( "dd MMM. yyyy" )
      // result: 01 Sep. 2006

      ? dDate:format( "dd-MM-yy hh:mm\h", Time() )
      // result: 01-09-06 18:07h

      dDate += 2

      ? dDate:format( "DDDD, MMMM ddd, at h \hour\s an\d m \minute\s" )
      // result: Sunday, September 3rd, at 18 hours and 7 minutes

      ? dDate:httpDate()
      // result: Sun, 03 Sep 2006 18:07:45
   RETURN


   CLASS DateFormatter
      EXPORTED:
      METHOD shortDay   INLINE Left( CDow(self), 3 )
      METHOD shortMonth INLINE Left( CMonth(self), 3 )
      METHOD time       INLINE Time()
      METHOD asString   INLINE DtoS(self)
      METHOD httpDate
      METHOD format
   ENDCLASS


   METHOD httpDate( cTime ) CLASS DateFormatter
   RETURN ::format( "DDD, dd MMM yyyy hh:mm:ss", cTime )


   METHOD format( cFormat, cTime ) CLASS DateFormatter
      LOCAL aToken := {}
      LOCAL cToken := ""
      LOCAL cChar

      IF cTime == NIL
         cTime := ::time()
      ENDIf

      FOR EACH cChar IN cFormat
         IF .NOT. cChar IN "DdMyhms"
            IF Len( cToken ) > 0
               AAdd( aToken, cToken )
            ENDIF
            IF cChar == "\"
               cToken := cChar
            ELSE
               AAdd( aToken, cChar )
               cToken := ""
            ENDIF
         ELSE
            cToken += cChar
         ENDIF
      NEXT
      AAdd( aToken, cToken )

      cFormat := ""
      FOR EACH cToken IN aToken
         IF cToken == ""
            LOOP
         ENDIF

         SWITCH cToken[1]
         CASE "y"
            IF Len( cToken ) == 4
               cFormat += Left( ::asString(), 4 )
            ELSE
               cFormat += SubStr( ::asString(), 3, 2 )
            ENDIF
            EXIT

         CASE "M"
            SWITCH Len( cToken )
            CASE 1
               cToken := SubStr( ::asString(), 5, 2 )
               IF cToken[1] == "0"
                  cFormat += cToken[2]
               ELSE
                  cFormat += cToken
               ENDIF
               EXIT
            CASE 2
               cFormat += SubStr( ::asString(), 5, 2 )
               EXIT
            CASE 3
               cFormat += ::shortMonth()
               EXIT
            DEFAULT
               cFormat += CMonth(self)
            END
            EXIT
            
         CASE "D"
            IF Len( cToken ) <= 3
               cFormat += Left( CDoW(self), Len(cToken) )
            ELSE
               cFormat += CDoW(self)
            ENDIF
            EXIT

         CASE "d"
            SWITCH Len(cToken)
            CASE 1
               cToken := Right( ::asString(), 2 )
               IF cToken[1] == "0"
                  cFormat += cToken[2]
               ELSE
                  cFormat += cToken
               ENDIF
            CASE 2
               cFormat += Right( ::asString(), 2 )
               EXIT
            DEFAULT
               cToken := Right( ::asString(), 2 )
               cFormat += IIf( cToken[1] == "0", cToken[2], cToken )

               DO CASE
               CASE cToken == "11" .OR. ;
                    cToken == "12"   ; cFormat += "th"
               CASE cToken[2] == "1" ; cFormat += "st"
               CASE cToken[2] == "2" ; cFormat += "nd"
               CASE cToken[2] == "3" ; cFormat += "rd"
               OTHERWISE
                  cFormat += "th"
               ENDCASE
            END
            EXIT

         CASE "h"
         CASE "m"
         CASE "s"
            SWITCH cToken[1]
            CASE "h" ; cChar := Left  (cTime,2)   ; EXIT
            CASE "m" ; cChar := SubStr(cTime,4,2) ; EXIT
            CASE "s" ; cChar := Right (cTime,2)   ; EXIT
            END

            IF Len( cToken ) == 1 .AND. cChar[1] == "0"
               cChar := cChar[2]
            ENDIF
            cFormat += cChar
            EXIT

         CASE "\"
            cFormat += SubStr( cToken, 2 )
            EXIT

         DEFAULT
            cFormat += cToken
         END
      NEXT
   RETURN cFormat
[]´s
Alexandre Santos (AlxSts)
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Classes e herança

Mensagem por JoséQuintas »

Gostei disso. Já deixa funções de data vinculadas ao tipo date(). Vou testar no Harbour.
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Classes e herança

Mensagem por JoséQuintas »

Tava brincando com um programinha antigo em clipper, e transformei em classe.
Por enquanto foi só teste: uma classe pra fazer todos os cadastros.
No fonte tem:
- A classe genérica, que seria a base pra tudo
- A classe herdada, para o cadastro de clientes
- O programa que faz uso da classe

A estrutura do arquivo usado é um cadastro básico, todos os campos string, com CDCODIGO(6), CDNOME(30), CDENDERECO(30), CDCIDADE(15), CDUF(2), CDCEP(8), sendo que o único tamanho obrigatório pra funcionar é o código com 6 dígitos.
Todo uso é pelo mouse, e e só compilar normal com hbmk2 programa
É um visual simples, que precisa ser melhorado, mas tá funcionando.

Código: Selecionar todos

#include "getexit.ch"
#include "inkey.ch"
#include "hbclass.ch"

*----------------------------------------------------------------
// programa principal

Procedure Main
   Request SIXCDX
   RddSetDefault("SIXCDX")
   Use \jpa\cordeiro\jpcadas
   Set Index To \jpa\cordeiro\jpcadas
   OrdSetFocus("numlan")
   SetColor("W/N,N/W,,,W/N")
   Set( _SET_EVENTMASK, INKEY_ALL ) // + HB_INKEY_GTEVENT 
   Tela := CadastroCliente()
   Tela:Execute()

*----------------------------------------------------------------
// Classe especifica pra cliente

CREATE CLASS CadastroCliente INHERIT CadastroGenerico
   Data cNome               INIT " "
   Data cEndereco           INIT " "
   Data cCidade             INIT " "
   Data cUf                 INIT " "
   Data cCep                INIT " "
   Method cmdSalvaClick(oGet)
   Method SetKeyField(cValue)
   Method SetFields(lBlank)
   Method Execute()
   EndClass

Method cmdSalvaClick(oGet) Class CadastroCliente
   If ::cCodigo == "*NOVO*"
      Goto Bottom
      ::cCodigo := StrZero(Val(jpcadas->cdCodigo)+1,6)
      Append Blank
      Replace jpcadas->cdCodigo With ::cCodigo
   Endif
   rLock()
   Replace ;
         jpcadas->cdEndereco With ::cEndereco, ;
         jpcadas->cdCidade With ::cCidade, ;
         jpcadas->cdUf With ::cUf, ;
         jpcadas->cdCep With ::cCep
   Skip 0
   Unlock   
   ::Reload()
   ::EditKeyEnabled     := .f.
   ::EditFieldsEnabled  := .f.
   ::EditCmdEnabled     := .f.
   ::NavegateCmdEnabled := .t.
   oGet:ExitState := GE_TOP
   Return NIL

Method SetKeyField(lEmpty) Class CadastroCliente // Pega chave
   lEmpty := iif(lEmpty==NIL,.f.,lEmpty)
   If lEmpty
      ::cCodigo := Space(6)
   Else
      ::cCodigo := jpcadas->cdCodigo
   Endif
   Return NIL
   
Method SetFields(lEmpty) Class CadastroCliente // Pega campos
   lEmpty := iif(lEmpty==NIL,.f.,lEmpty)
   If lEmpty
      ::cCodigo   := "*NOVO*"
      ::cNome     := Space(Len(jpcadas->cdNome))
      ::cEndereco := Space(Len(jpcadas->cdEndereco))
      ::cCidade   := Space(Len(jpcadas->cdCidade))
      ::cUf       := Space(Len(jpcadas->cdUf))
      ::cCep      := Space(Len(jpcadas->cdCep))
   Else
      ::cCodigo   := jpcadas->cdCodigo
      ::cNome     := jpcadas->cdNome
      ::cEndereco := jpcadas->cdEndereco
      ::cCidade   := jpcadas->cdCidade
      ::cUf       := jpcadas->cdUf
      ::cCep      := jpcadas->cdCep
   Endif
   Return NIL   

Method Execute() Class CadastroCliente // monta tela
   ::Reload()
   Clear
   @ 1, 0 Say "Codigo....:" Get ::cCodigo Picture "@K 999999" When ::EditKeyEnabled Valid ::FindKey(@::cCodigo)
   @ 2, 0 Say "Nome......:" Get ::cNome   When ::EditFieldsEnabled
   @ 3, 0 Say "Cidade....:" Get ::cCidade When ::EditFieldsEnabled
   @ 4, 0 Say "UF........:" Get ::cUf     When ::EditFieldsEnabled
   @ 5, 0 Say "Cep.......:" Get ::cCep    When ::EditFieldsEnabled
   @ 10, 0 Get ::cWait
   @ Row(), Col()+1 Get ::cCmdSalva       When ::EditCmdEnabled  Send Reader := {|Get|::CmdSalvaClick(Get)}
   @ Row(), Col()+1 Get ::cCmdCancela     When ::EditCmdEnabled  Send Reader := {|Get|::CmdCancelaClick(Get)}
   @ Row()+1, 0 Say " "
   @ Row(), Col()+1 Get ::cCmdInclui      When ::NavegateCmdEnabled Send Reader := {|Get|::CmdIncluiClick(Get)}
   @ Row(), Col()+1 Get ::cCmdAltera      When ::NavegateCmdEnabled Send Reader := {|Get|::CmdAlteraClick(Get)}
   @ Row(), Col()+1 Get ::cCmdExclui      When ::NavegateCmdEnabled Send Reader := {|Get|::CmdExcluiClick(Get)}
   @ Row(), Col()+1 Get ::cCmdSeguinte    When ::NavegateCmdEnabled Send Reader := {|Get|::CmdSeguinteClick(Get)}
   @ Row(), Col()+1 Get ::cCmdAnterior    When ::NavegateCmdEnabled Send Reader := {|Get|::CmdAnteriorClick(Get)}
   @ Row(), Col()+1 Get ::cCmdPrimeiro    When ::NavegateCmdEnabled Send Reader := {|Get|::CmdPrimeiroClick(Get)}
   @ Row(), Col()+1 Get ::cCmdUltimo      When ::NavegateCmdEnabled Send Reader := {|Get|::CmdUltimoClick(Get)}
   @ Row(), Col()+1 Get ::cCmdLocaliza    When ::NavegateCmdEnabled Send Reader := {|Get|::CmdLocalizaClick(Get)}
   @ Row(), Col()+1 Get ::cCmdSair        When ::NavegateCmdEnabled Send Reader := {|Get|::CmdSairClick(Get)}
   Read 

*----------------------------------------------------------------
// Classe Generica
   
CREATE CLASS CadastroGenerico
   Data cCodigo             INIT " "
   Data cCampoGenerico      INIT " "
   Data cWait               INIT " "
   Data ccmdSalva           INIT "Salva"
   Data ccmdCancela         INIT "Cancela"
   Data ccmdInclui          INIT "Inclui"
   Data ccmdAltera          INIT "Altera"
   Data ccmdExclui          INIT "Exclui"
   Data ccmdAnterior        INIT "Anterior"
   Data ccmdSeguinte        INIT "Seguinte"
   Data ccmdPrimeiro        INIT "Primeiro"
   Data ccmdLocaliza        INIT "Localiza"
   Data ccmdUltimo          INIT "Ultimo"
   Data ccmdSair            INIT "Sair"
   Data EditKeyEnabled      INIT .f.
   Data EditFieldsEnabled   INIT .f.
   Data EditCmdEnabled      INIT .f.
   Data NavegateCmdEnabled  INIT .t.
   Method cmdSalvaClick(oGet)
   Method cmdCancelaClick(oGet)
   Method cmdIncluiClick(oGet)
   Method cmdAlteraClick(oGet)
   Method cmdPrimeiroClick(oGet)
   Method cmdAnteriorClick(oGet)
   Method cmdSeguinteClick(oGet)
   Method cmdUltimoClick(oGet)
   Method cmdExcluiClick(oGet)
   Method cmdLocalizaClick(oGet)
   Method cmdSairClick(oGet)
   Method SetKeyField(cValue)
   Method SetFields(lBlank)
   Method Reload()
   Method Execute()
   Method FindKey(cKey)
   ENDCLASS

Method cmdSalvaClick(oGet) Class CadastroGenerico
   If ::cCodigo == "*NOVO*"
      Goto Bottom
      ::cCodigo := StrZero(Val(jpcadas->cdCodigo)+1,6)
      Append Blank
      Replace jpcadas->cdCodigo With ::cCodigo
   Endif
   rLock()
   Replace generico->CampoGenerico With cCampoGenerico
   Skip 0
   Unlock   
   ::Reload()
   ::EditKeyEnabled     := .f.
   ::EditFieldsEnabled  := .f.
   ::EditCmdEnabled     := .f.
   ::NavegateCmdEnabled := .t.
   oGet:ExitState := GE_TOP
   Return NIL

Method cmdCancelaClick(oGet) Class CadastroGenerico
   ::Reload()
   ::EditKeyEnabled     := .f.
   ::EditFieldsEnabled  := .f.
   ::EditCmdEnabled     := .f.
   ::NavegateCmdEnabled := .t.
   oGet:ExitState := GE_TOP
   Return NIL

Method cmdIncluiClick(oGet) Class CadastroGenerico
   ::cCodigo            := "*NOVO*"
   ::EditFieldsEnabled  := .t.
   ::EditCmdEnabled     := .t.
   ::NavegateCmdEnabled := .f.
   oGet:ExitState := GE_TOP
   Return NIL

Method cmdAlteraClick(oGet) Class CadastroGenerico
   ::EditFieldsEnabled  := .t.
   ::EditCmdEnabled     := .t.
   ::NavegateCmdEnabled := .f.
   oGet:ExitState := GE_TOP
   Return NIL

Method cmdExcluiClick(oGet) Class CadastroGenerico
   Delete
   Skip 0
   Skip
   ::Reload()
   oGet:ExitState := GE_TOP
   Return NIL

Method cmdSeguinteClick(oGet) Class CadastroGenerico
   Skip 
   ::Reload()
   oGet:ExitState := GE_TOP
   Return NIL
   
Method cmdAnteriorClick(oGet) Class CadastroGenerico
   Skip -1
   ::Reload()
   oGet:ExitState := GE_TOP
   Return NIL
   
Method cmdPrimeiroClick(oGet) Class CadastroGenerico
   GoTo Top
   ::Reload()
   oGet:ExitState := GE_TOP
   Return NIL
   
Method cmdUltimoClick(oGet) Class CadastroGenerico
   Goto Bottom
   ::Reload()
   oGet:ExitState := GE_TOP
   Return NIL
   
Method cmdLocalizaClick(oGet) Class CadastroGenerico
   ::SetKeyField(.t.)
   ::SetFields(.t.)
   ::EditKeyEnabled     := .t.
   ::NavegateCmdEnabled := .f.
   ::EditCmdEnabled     := .t.
   oGet:ExitState := GE_TOP
   Return NIL

Method cmdSairClick(oGet) Class CadastroGenerico
   KeyBoard Chr(27)
   oGet:ExitState := GE_TOP
   Return NIL

Method SetKeyField(lEmpty) Class CadastroGenerico
   lEmpty := iif(lEmpty==NIL,.f.,lEmpty)
   If lEmpty
      ::cCodigo := Space(6)
   Else
      ::cCodigo := jpcadas->cdCodigo
   Endif
   Return NIL
   
Method SetFields(lEmpty) Class CadastroGenerico
   lEmpty := iif(lEmpty==NIL,.f.,lEmpty)
   If lEmpty
      ::cCodigo   := "*NOVO*"
      ::cNome     := Space(Len(jpcadas->cdNome))
   Else
      ::cCodigo   := jpcadas->cdCodigo
      ::cNome     := jpcadas->cdNome
   Endif
   Return NIL   

Method Reload() Class CadastroGenerico
   ::SetKeyField()
   ::SetFields()
   For nCont = 1 to Len(GetList)
      GetList[nCont]:Display()
   Next
   Return NIL

Method Execute() Class CadastroGenerico
   ::Reload()
   Clear
   @ 1, 0 Say "Codigo....:" Get ::cCodigo Picture "@K 99999" When ::EditKeyEnabled Valid ::FindKey(@::cCodigo)
   @ 2, 0 Say "Nome......:" Get ::cNome   When ::EditFieldsEnabled
   @ 10, 0 Get ::cWait
   @ Row(), Col()+1 Get ::cCmdSalva       When ::EditCmdEnabled  Send Reader := {|Get|::CmdSalvaClick(Get)}
   @ Row(), Col()+1 Get ::cCmdCancela     When ::EditCmdEnabled  Send Reader := {|Get|::CmdCancelaClick(Get)}
   @ Row()+1, 0 Say " "
   @ Row(), Col()+1 Get ::cCmdInclui      When ::NavegateCmdEnabled Send Reader := {|Get|::CmdIncluiClick(Get)}
   @ Row(), Col()+1 Get ::cCmdAltera      When ::NavegateCmdEnabled Send Reader := {|Get|::CmdAlteraClick(Get)}
   @ Row(), Col()+1 Get ::cCmdExclui      When ::NavegateCmdEnabled Send Reader := {|Get|::CmdExcluiClick(Get)}
   @ Row(), Col()+1 Get ::cCmdSeguinte    When ::NavegateCmdEnabled Send Reader := {|Get|::CmdSeguinteClick(Get)}
   @ Row(), Col()+1 Get ::cCmdAnterior    When ::NavegateCmdEnabled Send Reader := {|Get|::CmdAnteriorClick(Get)}
   @ Row(), Col()+1 Get ::cCmdPrimeiro    When ::NavegateCmdEnabled Send Reader := {|Get|::CmdPrimeiroClick(Get)}
   @ Row(), Col()+1 Get ::cCmdUltimo      When ::NavegateCmdEnabled Send Reader := {|Get|::CmdUltimoClick(Get)}
   @ Row(), Col()+1 Get ::cCmdLocaliza    When ::NavegateCmdEnabled Send Reader := {|Get|::CmdLocalizaClick(Get)}
   @ Row(), Col()+1 Get ::cCmdSair        When ::NavegateCmdEnabled Send Reader := {|Get|::CmdSairClick(Get)}
   Read 

Method FindKey(cCodigo) Class CadastroGenerico
   cCodigo := StrZero(Val(cCodigo),6)
   Seek cCodigo
   ::SetFields()
   Return .t.
*----------------------------------------------------------------

José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
Avatar do usuário
NiltonGM
Usuário Nível 3
Usuário Nível 3
Mensagens: 397
Registrado em: 05 Jun 2014 23:47
Localização: Caieiras/SP

Classes e herança

Mensagem por NiltonGM »

Oi Zeh, muito interessante, estou fazendo algo parecido, eu não sabia que podíamos usar os métodos e propriedades da CLASS pai dentro da CLASS filha sem usar o ::Super():<metodo ou propriedade da class pai>
Nesse caso, o Super() é só por motivo de compatibilidade?
Fiz alguns testes com herança, o Super() é para quando queremos usar um método ou propriedade do pai que tem o mesmo nome na class filha. Muito legal.
Nilton Medeiros
nilton@sistrom.com.br
Avatar do usuário
JoséQuintas
Administrador
Administrador
Mensagens: 20267
Registrado em: 26 Fev 2007 11:59
Localização: São Paulo-SP

Classes e herança

Mensagem por JoséQuintas »

NiltonGM escreveu:Nesse caso, o Super() é só por motivo de compatibilidade?
Não. Acabamos usando na prática.
Um exemplo simples, fazendo uso do SUPER.

Código: Selecionar todos

CLASS Cadastro
   METHOD Exclui()
   ENDCLASS

METHOD Exclui()
   IF MsgYesNo( "Confirma" )
     DELETE
   ENDIF
   RETURN NIL

Código: Selecionar todos

CLASS OutroCadastro INHERIT Cadastro
   METHOD Exclui()
   END CLASS

METHOD Exclui()
   IF EmUso()
      MsgStop( "Não pode excluir, está em uso" )
   ELSE
      ::SUPER:Exclui()
   ENDIF
   RETURN NIL
José M. C. Quintas
Harbour 3.2, mingw, gtwvg mt, fivewin 25.04, multithread, dbfcdx, MySQL, ADOClass, PDFClass, SefazClass, (hwgui mt), (hmg3), (hmg extended), (oohg), PNotepad, ASP, stored procedure, stored function, Linux (Flagship/harbour 3.2)
"The world is full of kings and queens, who blind our eyes and steal our dreams Its Heaven and Hell"

https://github.com/JoseQuintas/
lwinter
Usuário Nível 3
Usuário Nível 3
Mensagens: 123
Registrado em: 07 Mar 2011 12:08
Localização: Campinas - SP

Classes e herança

Mensagem por lwinter »

Gente muito legal os comentários de vocês.
Estou fazendo uma classe para trabalhar com classe e o código fonte final fica realmente muito mais fácil e intuitivo. Inclusive para dar manutenção.
:{
Responder