Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > OOP
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 29-11-2016
Avatar de AgustinOrtu
[AgustinOrtu] AgustinOrtu is offline
Miembro Premium
NULL
 
Registrado: ago 2013
Ubicación: Argentina
Posts: 1.858
Poder: 15
AgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en bruto
Sobrecarga de operadores de clase

Pues eso, aunque se supone que Delphi no soporta sobrecargar los operadores de clase como si sucede con los tipos records o registros, existe cierta sintaxis que lo hace posible, apartentemente no documentada ni oficial

En fin, no se como lo habra descubierto el que lo hizo, o de donde lo saco. La cuestion es que ha publicado dos fragmentos de codigo en GitHub, aca y aca

Sorprendentemente este codigo compila, funciona y no hay fugas de memoria, en Delphi 2010 y Delphi 10.1 Berlin, asi que supongo que "la compatibilidad se mantiene" en todas las versiones del medio.

Código Delphi [-]
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Classes;

type
  TStringListHelper = class helper for TStringList
  public
    class function &&op_In(const Value: string; Target: TStringList): Boolean; static;
    class function &&op_LogicalOr(A, B: TStringList): TStringList; static;
  end;

class function TStringListHelper.&&op_In(const Value: string; Target: TStringList): Boolean;
begin
  Result := Target.IndexOf(Value) <> -1;
end;

class function TStringListHelper.&&op_LogicalOr(A, B: TStringList): TStringList;
begin
  if A <> nil then
    Result := A
  else
    Result := B;
end;

procedure Test;
var
  StringListA, StringListB, StringListC: TStringList;
begin
  StringListA := nil;
  StringListB := TStringList.Create;
  try
    StringListB.Add('Hola mundo');
    StringListC := StringListA or StringListB; // -> StringListC apunta al mismo objeto que StringListB
    Writeln('StringListB.Text: ' + StringListB.Text); // imprime hola mundo
    Writeln('StringListC.Text: ' + StringListC.Text); // imprime hola mundo
    Writeln(BoolToStr(StringListB = StringListC, True)); // imprime True
    Writeln(BoolToStr('Hola mundo' in StringListB, True)); // imprime True
    Writeln(BoolToStr('blabla' in StringListB, True)); // imprime False
  finally
    StringListB.Free;
  end;
end;

begin
  ReportMemoryLeaksOnShutdown := True;
  try
    Test;
    Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Me parece algo realmente poderoso y peligroso al mismo tiempo, no he podido ordenar mis ideas por el momento

Realmente algo como esto si que es util para escribir codigo mas elegante y sencillo. Muchas veces se emplea el uso de records como envolturas de clases o tipos primitivos ya que ellos son los unicos con los que se pueden sobrecargar los operadores; pero esto lo lleva a otro nivel

De hecho es posible hasta con genericos como se puede ver en el codigo del autor
Responder Con Cita
  #2  
Antiguo 29-11-2016
Avatar de jhonny
jhonny jhonny is offline
Jhonny Suárez
 
Registrado: may 2003
Ubicación: Colombia
Posts: 7.058
Poder: 29
jhonny Va camino a la famajhonny Va camino a la fama
Sí que sí, bastante interesante, me he preguntado desde hace tiempo ¿Cuál será la razón para que la sobrecarga de operadores no esté soportada de manera nativa en las clases?, pues como bien indicas esto es poderoso aunque a la vez peligroso.

¿Cómo habrá sabido este personaje que tenía que anteponer &&op_ al nombre de cada operador?

Bastante interesante, el truco y lo que habrá detrás de dicha conclusión.

P.D: Sólo anotar, que me parece muy curiosa la observación que hace un usuario diciendo que no funciona en Records
__________________
Lecciones de mi Madre. Tema: modificación del comportamiento, "Pará de actuar como tu padre!"

http://www.purodelphi.com/
http://www.nosolodelphi.com/

Última edición por jhonny fecha: 29-11-2016 a las 06:28:20. Razón: Quitar gazapo
Responder Con Cita
  #3  
Antiguo 29-11-2016
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Interesante, Agustín. Al estar depurando, con la ventana CPU, me parece haber visto nombres similares a esos. Quizá de ahí el descubridor obtuvo los nombres "reales" que les da el compilador a esos métodos.

Sólo los compiladores con ARC (Delphi para dispositivos móviles) admiten la sobrecarga "formal" de operadores en clases, ya que en ellos puede uno despreocuparse por las instancias "intermedias" que se crean a mitad de algunas operaciones, dado que todos los objetos usan un contador de referencias, tal como lo hacen los String en cualquiera de los compiladores de Delphi.

Creo que la explicación al truco podría estar en que sólo el revisor sintáctico del compilador impide la declaración en clases, pero el resto de la compilación se realiza asumiendo que ya se superaron las validaciones sintácticas de plataforma y procede sin restricciones (asumiendo también el nombre transformado del método).

Resulta tentador empezar a aprovechar esta puerta trasera en los compiladores de escritorio, pero ya aprendí la lección, y es mejor prescindir de características del compilador no oficiales. Además hay que tener cuidado no de aplicar ningún operador que deje un objeto "suelto" por ahí.

¡Qué hallazgo!
Responder Con Cita
  #4  
Antiguo 29-11-2016
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.264
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por AgustinOrtu Ver Mensaje

Código Delphi [-]
   ...
    Writeln(BoolToStr('Hola mundo' in StringListB, True)); // imprime True
    Writeln(BoolToStr('blabla' in StringListB, True)); // imprime False
   ...
Este me ha gustado mucho.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #5  
Antiguo 29-11-2016
Avatar de AgustinOrtu
[AgustinOrtu] AgustinOrtu is offline
Miembro Premium
NULL
 
Registrado: ago 2013
Ubicación: Argentina
Posts: 1.858
Poder: 15
AgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en bruto
Marco Cantú ha confirmado que esto es una puerta trasera, que es una característica no intencionalmente puesta a nuestro alcance, tal y como comenta nuestro amigo Al González

Los operadores que crean objetos intermedios seguro que ocasionan fugas de memoria.

Aún así me parece un juguetito muy interesante y que tiene mucha tela por donde cortar.

Esta es la lista completa de operadores:

Cita:
class operator class function
Implicit &&op_Implicit
Explicit &&op_Explicit
Negative &&op_UnaryNegation
Positive &&op_UnaryPlus
Inc &&op_Increment
Dec &&op_Decrement
LogicalNot &&op_LogicalNot
Trunc &&op_Trunc
Round &&op_Round
In &&op_In
Equal &&op_Equality
NotEqual &&op_Inequality
GreaterThan &&op_GreaterThan
GreaterThanOrEqual &&op_GreaterThanOrEqual
LessThan &&op_LessThan
LessThanOrEqual &&op_LessThanOrEqual
Add &&op_Addition
Subtract &&op_Subtraction
Multiply &&op_Multiply
Divide &&op_Division
IntDivide &&op_IntDivide
Modulus &&op_Modulus
LeftShift &&op_LeftShift
RightShift &&op_RightShift
LogicalAnd &&op_LogicalAnd
LogicalOr &&op_LogicalOr
LogicalXor &&op_ExclusiveOr
BitwiseAnd &&op_BitwiseAnd
BitwiseOr &&op_BitwiseOr
BitwiseXor &&op_BitwiseXOR
Include &&op_Include
Exclude &&op_Exclude
A mi también me ha gustado mucho el operador in. Y el del or para usar un objeto u otro en caso de nil también me parece que tiene mucho juego

En fin, es cuestión de creatividad. Pero ya hemos sido advertidos: es posible que solucionen este defecto

Última edición por AgustinOrtu fecha: 29-11-2016 a las 11:10:44.
Responder Con Cita
  #6  
Antiguo 29-11-2016
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Para mi siempre ha sido algo natural la sobrecarga de operadores que uso bastante, ahorrándome código y proporcionando limpieza e intuición al código. Estoy hablando de C++
Siempre lo he echado en falta en delphi.

Saludos.
Responder Con Cita
  #7  
Antiguo 29-11-2016
Avatar de AgustinOrtu
[AgustinOrtu] AgustinOrtu is offline
Miembro Premium
NULL
 
Registrado: ago 2013
Ubicación: Argentina
Posts: 1.858
Poder: 15
AgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en bruto
En C++ o los lenguajes con recoleccion de basura es seguro tener operadores de clase.

En Delphi que no es necesariamente el caso, puede haber muchas fugas de memoria, y creo que ese es el motivo por el cual no tenemos a nuestra disposicion sobrecarga de operadores. Al menos no para el compilador para Windows; los que implementan ARC, como señalo Al, si que permiten la sobrecarga

Los record son un caso especial porque Delphi se encarga de manejar la memoria por nosotros y entonces no hay problema

A mi tambien siempre me hacian mucha falta en Delphi.. seria muy bueno poder tener esta sintaxis de manera oficial, por lo menos en interfaces que si implementan el mecanismo de contador de referencias

Otro detalle es que no necesariamente hay que usar un ayudante de clase como esta mas arriba. Es posible utilizar una subclase para lograr el mismo efecto; o tambien el viejo truco de la clase interpuesta

Código Delphi [-]
  TStringListEx = class(TStringList)
  public
    class function &&op_In(const Value: string; Target: TStringListEx): Boolean; static;
    class function &&op_LogicalOr(A, B: TStringListEx): TStringListEx; static;
  end;

Código Delphi [-]
  TStringList = class(Classes.TStringList)
  public
    class function &&op_In(const Value: string; Target: TStringList): Boolean; static;
    class function &&op_LogicalOr(A, B: TStringList): TStringList; static;
  end;
Responder Con Cita
  #8  
Antiguo 29-11-2016
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Hablando de estas cosas, yo sueño con el día en que pueda escribir en Delphi "expresiones de asignación" como
Código Delphi [-]
...

If ... Then
  If (A := B) > 10 Then  // <---
    ...

...
en lugar de
Código Delphi [-]
...

If ... Then
  If TghSys.SetInt (A, B) > 10 Then  // <---
    ...

...
que suelo escribir en lugar de
Código Delphi [-]
...

If .. Then
Begin  // <---
  A := B;  // <---

  If A > 10 Then  // <---
    ...
End;  // <---

...

Un abrazo esperanzador.

Al González.

Última edición por Al González fecha: 29-11-2016 a las 19:15:47.
Responder Con Cita
  #9  
Antiguo 29-11-2016
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por AgustinOrtu Ver Mensaje
En C++ o los lenguajes con recoleccion de basura es seguro tener operadores de clase.]
¿C++ tiene recolector de basura?

Y si no, ¿por qué en C++ sí es seguro y en Delphi no?

LineComment Saludos
Responder Con Cita
  #10  
Antiguo 29-11-2016
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por Al González Ver Mensaje
yo sueño con el día en que pueda escribir en Delphi "expresiones de asignación" como
Código Delphi [-]
...

If ... Then
  If (A := B) > 10 Then  // <---
    ...

...
¡Anda! Ahora sí me sorprendiste. ¿Tú soñando con una característica típica del lenguaje C?

LineComment Saludos
Responder Con Cita
  #11  
Antiguo 29-11-2016
Avatar de AgustinOrtu
[AgustinOrtu] AgustinOrtu is offline
Miembro Premium
NULL
 
Registrado: ago 2013
Ubicación: Argentina
Posts: 1.858
Poder: 15
AgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en brutoAgustinOrtu Es un diamante en bruto
Ay ay me equivoque

El que recolecta basura era el C#
Responder Con Cita
  #12  
Antiguo 29-11-2016
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.037
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Cita:
Empezado por roman Ver Mensaje
¡Anda! Ahora sí me sorprendiste. ¿Tú soñando con una característica típica del lenguaje C?
Me lo has quitado de la boca...
Responder Con Cita
  #13  
Antiguo 29-11-2016
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Cita:
Empezado por roman Ver Mensaje
¡Anda! Ahora sí me sorprendiste. ¿Tú soñando con una característica típica del lenguaje C?
El lenguaje C tiene algunas cosas muy buenas, Román.
Responder Con Cita
  #14  
Antiguo 29-11-2016
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por Al González Ver Mensaje
El lenguaje C tiene algunas cosas muy buenas, Román.
Eso lo sé, pero pensé que tú no

Pero ya en serio, me causa curiosidad el uso que deseas, quizá por no tener contexto. En lo particular, esa característica (que la asignación sea un operador) casi sólo la uso para ciclos en los que obtengo y uso un dato:

Código:
/*
  DameRegistro devuelve el siguiente registro o FALSE si no hay más registros
*/
WHILE registro = DameOtro() DO
BEGIN
  MuestraRegistro(registro)
END
En otros casos, puede devenir en una lectura confusa.

LineComment Saludos
Responder Con Cita
  #15  
Antiguo 29-11-2016
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por AgustinOrtu Ver Mensaje
Ay ay me equivoque

El que recolecta basura era el C#
Ok. Pero entonces, ¿qué hace que C++ si pueda tener el operator overloading y delphi no?

LineComment Saludos
Responder Con Cita
  #16  
Antiguo 01-12-2016
Avatar de jhonny
jhonny jhonny is offline
Jhonny Suárez
 
Registrado: may 2003
Ubicación: Colombia
Posts: 7.058
Poder: 29
jhonny Va camino a la famajhonny Va camino a la fama
Un parentesis pequeño, sólo para mostrar el recolector de basuras de C#



P.D: Perdón, no pude evitarlo.
__________________
Lecciones de mi Madre. Tema: modificación del comportamiento, "Pará de actuar como tu padre!"

http://www.purodelphi.com/
http://www.nosolodelphi.com/
Responder Con Cita
  #17  
Antiguo 01-12-2016
Avatar de mamcx
mamcx mamcx is offline
Moderador
 
Registrado: sep 2004
Ubicación: Medellín - Colombia
Posts: 3.911
Poder: 25
mamcx Tiene un aura espectacularmamcx Tiene un aura espectacularmamcx Tiene un aura espectacular
Cita:
Empezado por roman Ver Mensaje
Ok. Pero entonces, ¿qué hace que C++ si pueda tener el operator overloading y delphi no?

LineComment Saludos
QUe C++ es el frankestein de los lenguajes y le inyectan toda caracteristica bajo el sol. Prácticamente puedes programar como si estuvieras en otro lenguaje abusando de C++ como te de la gana.


Delphi, por el contrario, fue derivado de alguien que *diseño* el lenguaje:

http://pascal-central.com/ppl/#Origins

Cita:
Niklaus Wirth completed development of the original Pascal programming language in 1970. He based it upon the block structured style of the Algol programming language. There were two original goals for Pascal.

According to the Pascal Standard (ISO 7185), these goals were to a) make available a language suitable for teaching programming as a systematic discipline based on fundamental concepts clearly and naturally reflected by the language, and b) to define a language whose implementations could be both reliable and efficient on then-available computers.
Delphi/Pascal tiene un compilador veloz *PRECISAMENTE* por ser tan anti-C++ como es posible.

----

Ahora, lograr poder sobrecargar operadores no es en si algo tan problematico... excepto que en los lenguajes imperativos existe una división entre expresiones, clases, tipos, statements (bloques), etc. Si Delphi fuera un lenguaje unificado a todo es una expresión esto sería un cambio trivial.

Tambien *supongo* que no seria trivial el darle una disponibilidad universal y que efectos tendria con el chequeo e intersección de tipos y si quedaria oscurecido el código por su uso. Esto no lo he pensando asi que es pura especulación.
---

En ultimas hay cambios a los lenguajes que los alteran de forma fundamental. Intentar agregarles cosas puede terminar siendo poco "idiomático" o convertirse en una característica de nicho poco usada pero que igual tiene su coste en mantenimiento e implementación.


P.D: Esta es una caracteristica que no es tan problematica si esta bien implementada, y NO SE PERMITE redefinir o crear nuevos operadores al vuelo (un problema que termina creando diversos codigos con el mismo operador pero diferente semantica!). Si esta limitado a unos pocos es muy util!
__________________
El malabarista.
Responder Con Cita
  #18  
Antiguo 01-12-2016
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
¿Qué tendrá C/C++ que es tan envidiado y odiado?

Saludos.
Responder Con Cita
  #19  
Antiguo 01-12-2016
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.037
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Cita:
Empezado por escafandra Ver Mensaje
¿Qué tendrá C/C++ que es tan envidiado y odiado?
Saludos.
C me gusta, C++ no me gusta
Responder Con Cita
  #20  
Antiguo 01-12-2016
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 2.197
Poder: 20
escafandra Tiene un aura espectacularescafandra Tiene un aura espectacular
Cita:
Empezado por Casimiro Notevi Ver Mensaje
C me gusta, C++ no me gusta
Ya pero características propias de C++ son tan envidiadas cómo el propio C. No será tan malo, diho yo. A mi me gustan ambos y delphi también.

Saludos
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Sobrecarga de propiedades jzginez OOP 2 21-02-2014 17:58:09
Duda operadores de clase waremovil C++ Builder 4 22-02-2012 08:58:46
Sobrecarga de constructores vejerf OOP 2 06-06-2008 12:52:36
Polimorfismo y sobrecarga davitcito Varios 3 15-04-2005 19:56:11
sobrecarga de operadores zuriel_zrf Varios 1 11-09-2003 13:08:36


La franja horaria es GMT +2. Ahora son las 07:49:46.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi