Clipper On Line • Ver Tópico - Classes e herança

Classes e herança

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

Moderador: Moderadores

 

Classes e herança

Mensagempor JoséQuintas » 10 Ago 2012 20:58

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
#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
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

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.

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.

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, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18161
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Classes e herança

Mensagempor ANDRIL » 10 Ago 2012 22:08

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 de usuário

ANDRIL
Usuário Nível 5

Usuário Nível 5
 
Mensagens: 1271
Data de registro: 06 Jul 2004 00:44
Curtiu: 12 vezes
Mens.Curtidas: 46 vezes

Classes e herança

Mensagempor JoséQuintas » 11 Ago 2012 22:41

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, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18161
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Classes e herança

Mensagempor fladimir » 12 Ago 2012 19:07

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.
Avatar de usuário

fladimir
Colaborador

Colaborador
 
Mensagens: 2436
Data de registro: 15 Nov 2006 19:21
Curtiu: 28 vezes
Mens.Curtidas: 157 vezes

Classes e herança

Mensagempor alxsts » 13 Ago 2012 14:51

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:
// 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)
alxsts
Colaborador

Colaborador
 
Mensagens: 2945
Data de registro: 12 Ago 2008 15:50
Cidade/Estado: São Paulo-SP-Brasil
Curtiu: 21 vezes
Mens.Curtidas: 248 vezes

Classes e herança

Mensagempor JoséQuintas » 01 Set 2012 19:18

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, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18161
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Classes e herança

Mensagempor JoséQuintas » 02 Set 2012 06:19

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.

#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, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18161
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Classes e herança

Mensagempor NiltonGM » 08 Mar 2019 11:51

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 de usuário

NiltonGM
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 393
Data de registro: 05 Jun 2014 23:47
Cidade/Estado: Caieiras/SP
Curtiu: 249 vezes
Mens.Curtidas: 25 vezes

Classes e herança

Mensagempor JoséQuintas » 08 Mar 2019 15:16

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.

CLASS Cadastro
   METHOD Exclui()
   ENDCLASS

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


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, multithread, dbfcdx, ADO+MySql, PNotepad
"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 de usuário

JoséQuintas
Membro Master

Membro Master
 
Mensagens: 18161
Data de registro: 26 Fev 2007 11:59
Cidade/Estado: São Paulo-SP
Curtiu: 15 vezes
Mens.Curtidas: 1215 vezes

Classes e herança

Mensagempor Eric.Developer » 10 Mar 2019 01:22

Isso mesmo e ainda mais. Você pode adotar combinações, estratégias, comportamentos diferentes para o mesmo método, isso inclui parâmetros e retorno.

METHOD TFilho:openFile( cFileName ) // --> lSuccess
   local lSuccess
   
   lSuccess:=::Super:openFile( cFileName )
   novos códigos.... depois
   return lSuccess

ou
   
METHOD TFilho:openFile() // --> lSuccess
   novos códigos.... substituicao
   return .f.
   
ou

METHOD TFilho:openFile( cFileName ) // --> lSuccess
   
   novos códigos.... antes
   return ::Super:openFile( cFileName )
   
ou

METHOD TFilho:openFile( cFileName ) // --> lSuccess
   // anulando
   return .f.
   
ou

METHOD TFilho:openFile( a, b, ... ) // --> lSuccess
   
   novos códigos.... antes
   return ::Super:openFile( a, b, ... ) // Recurso exclusivo do Harbour


NiltonGM escreveu: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.


Criar, Herdar Classes, sobrecarga, etc é muito simples. Códigos, sintaxes, instruções técnicas, talvez sejam apenas 65% do processo, o restante é ser, pensar de forma organizada, modular, para criar boas modelagens, classes úteis. Tais características você desempenha em qualquer etapa do desenvolvimento, tarefas cotidianas, ao criar funções, dando nomes a arquivos.

Todo programador Clipper 5.x, já é um usuário de OOP, mesmo que nunca tenha instanciado diretamente uma das classes existentes.
DBEdit é um objeto instanciado da classe TbrowseDB.

@10,10 SAY 'TESTE' GET cW1 VALID ! EMPTY(cW1)
@11,10 SAY 'TESTE' GET cW2 VALID ! EmptyGet()
Neste exemplo Clipper, foram feitas duas instâncias (2 objetos) indiretas da class Get e estão disponíveis para uso. Para saber durante o VALID se a variável foi preenchida, o programador deveria usar a instância e não o nome de cada variável, validar sem saber o nome.
Delphi, SQL, FastReport | Xailer VxH Fivewin Minigui Hwgui [x]Harbour
Contate-me: Desenvolvimentos em geral | Treinamentos
Overview/Download: Xailer / Harbour Ferramenta profissional e mais completa.
Avatar de usuário

Eric.Developer
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 161
Data de registro: 31 Ago 2010 22:16
Curtiu: 0 vez
Mens.Curtidas: 8 vezes

Classes e herança

Mensagempor lwinter » 20 Ago 2019 15:52

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.
:{
lwinter
Usuário Nível 3

Usuário Nível 3
 
Mensagens: 123
Data de registro: 07 Mar 2011 12:08
Cidade/Estado: Campinas - SP
Curtiu: 1 vez
Mens.Curtidas: 12 vezes




Retornar para Harbour

Quem está online

Usuários vendo este fórum: Google [Bot] e 14 visitantes


Ola Amigo, espero que meu site e forum tem lhe beneficiado, com exemplos e dicas de programacao.
Entao divulgue o link da Doacao abaixo para seus amigos e redes sociais ou faça uma doacao para o site forum...
MUITO OBRIGADO PELA SUA DOACAO!
Faça uma doação para o forum
cron
v
Olá visitante, seja bem-vindo ao Fórum Clipper On Line!
Efetue o seu login ou faça o seu Registro