Duda, reemplazo de IF por Polimorfismo.

Iniciado por n-utz, 29 Junio 2017, 23:24 PM

0 Miembros y 1 Visitante están viendo este tema.

n-utz

Buenas gente, les traigo un problema complicado, por lo menos para mi. Estoy haciendo un curso de Orientación a Objetos y nos propusieron un ejercicio. El ejercicio está compuesto por una clase Padre denominada Numeros, y dos Subclases denominadas Fraccion y Entero.

Obviamente la clase Fraccion está compuesta por dos colaboradores internos, numerador y denominador, mientras que la clase Entero solo por el colaborador interno value.

Me dieron test's implementados con errores los cuales yo tengo que corregir. Son varios, pero lo que no entiendo es la escencia de como comenzar a resolver todos, ya que todos los tengo que resolver con polimorfismo, les cuento el problema poniendoles de ejemplo el primer test a corregir:

Tengo que realizar una suma entre dos numeros, pero uno de ello es entero y otro es una fracción, entonces tengo que hacerle saber que son de tipos distintos a través del polimorfismo y hacer la suma correspondiente. La idea es resolverlo sin utilizar IF'S y solo con Polimorfismo

La verdad es un curso que estoy haciendo y estoy muy metido, queriendo aprender, soy muy novato en objetos, por eso vengo acá a que me ayuden a plantear el problema dandome el primer empujón que preciso.

Ideas? Tips? Ayudas?

Explayo lo que analice hasta ahora porque ni yo sé bien que pide..

Supongo que cuando haga esto:

InstanciaDeEntero.suma(InstanciaDeFraccion);

El metodo deberia averiguar por su cuenta si el parametro que le estoy pasando es una fraccion o un entero, una vez que lo haga realizar las operaciones correspondientes y devolver el valor, pero lo principal es como hacer que reconozca qué es el parámetro por el polimorfismo y no con un simple IF.

Eleкtro

#1
Hola.

Me da la sensación de que no tienes del todo claro el concepto de Polimorfismo. El Polimorfismo no tiene nada que ver con poder usar o no poder usar ifs/condicionales, eso sería en la parte de la implementación y por supuesto puedes usar lo que te venga en gana para desarrollar y resolver la lógica/algoritmo de la implementación...

El Polimorfismo simplemente se refiere a la capacidad de poder variar la implementación de un método o propiedad, de tal forma que, en una derivación de clase con un método o propiedad que haya sido heredado de la clase base, dicho método podrá ser invalidado (overriden) para poder realizar diferentes acciones dependiendo del tipo de objeto que se le envie.

En resumen, podemos referirnos al Polimorfismo como derivaciones de clases que representan un mismo elemento base (ej. clase base 'Animal', derivación 'Perro' y derivación 'Gato') pero difieren en la implementación de sus métodos o propiedades heredadas.

El Polimorfismo solamente se aplica a métodos o propiedades que hayan sido declarados con el keyword Overridable, es decir el término Overridable en .NET equivale a decir Polimorfismo, es lo mismo, y todo lo demás son métodos o propiedades considerados invariantes (dicho de otra manera: no son polimorfos). Por ende, para empezar a hacer uso del Polimorfismo simplemente se debe declarar una clase base con miembros (métodos o propiedades) overridables, luego heredar esa clase e invalidar (override) el método polimorfo/overridable para modificar su implementación y con ello su comportamiento en función al tipo de argumento que le pasemos al método.

Por ejemplo, al aplicar el Polimorfismo lo hariamos con la idea de representar un número con una clase llamada "NumeroBase", un número entero con una clase derivada y llamada "NumeroInt" y un número decimal con otra clase derivada y llamada "NumeroDec". En esencia, ambas derivaciones representan lo mismo, un número, así que la clase "NumeroBase" debería ser capaz de representar ambos tipos de números y llevar a cabo el mismo tipo de acciones que sus derivaciones (aunque hacerlo es opcional, no se debe considerar como una regla estricta al seguir las directrices de diseño de la implementación del Polimorfismo). "NumeroInt" y "NumeroDec" simplemente ampliarian la implementación de "NumeroBase" (gracias al Polimorfismo) para tratar distintos tipos de números con sus respectivas...diferencias (las diferencias que hagan singular a un número entero, o a un número decimal).

Un ejemplo muy breve y sencillo (extraido de la MSDN) para ayudar a entender el Polimorfismo:

Código (vbnet) [Seleccionar]
MustInherit Public Class Shape
   Public MustOverride Sub Paint(g As Graphics, r As Rectangle)
End Class

Public Class Ellipse : Inherits Shape
   Public Overrides Sub Paint(g As Graphics, r As Rectangle)
       g.drawEllipse(r)
   End Sub
End Class

Public Class Box : Inherits Shape
   Public Overrides Sub Paint(g As Graphics, r As Rectangle)
       g.drawRect(r)
   End Sub
End Class





Existen muchas formas o visión de ideas para implementar tu ejercicio, y habría que analizar bien los detalles expuestos en el ejercicio para saber exactamente lo que pide hacer e idear la forma óptima de hacerlo. Yo me limitaré a mostrarte este ejemplo que he escrito en VB.NET haciendo uso del Polimorfismo y Generics que puedes adaptar o extender según tus necesidades. Si el ejercicio es en C#, entonces puedes usar cualqueir conversor online de C# <> VB.NEt, como por ejemplo http://converter.telerik.com/

Código (vbnet) [Seleccionar]
Public MustInherit Class Number(Of T)

   Public MustOverride Property Value As T
   Public MustOverride Function Sum(ByVal value As T) As T

End Class


Código (vbnet) [Seleccionar]
' Número de tipo entero...
Public NotInheritable Class NumberInt : Inherits Number(Of Integer)

   Public Overrides Property Value As Integer

   Public Sub New(ByVal value As Integer)
       Me.Value = value
   End Sub

   Public Overrides Function Sum(ByVal value As Integer) As Integer
       Return (Me.Value + value)
   End Function

End Class


Código (vbnet) [Seleccionar]
' Número de tipo decimal...
Public NotInheritable Class NumberDec : Inherits Number(Of Decimal)

   Public Overrides Property Value As Decimal

   Private Sub New()
   End Sub

   Public Sub New(ByVal value As Decimal)
       Me.Value = value
   End Sub

   Public Overrides Function Sum(ByVal value As Decimal) As Decimal
       Return (Me.Value + value)
   End Function

End Class


Código (vbnet) [Seleccionar]
' Número de cualquier tipo...
Public NotInheritable Class Number : Inherits Number(Of IConvertible)

   Public Overrides Property Value As IConvertible

   Public Sub New(ByVal value As IConvertible)
       If Not Me.IsNumericTypeCode(value) Then
           Throw New ArgumentException("Bad numeric typecode.", "value")
       End If
       Me.Value = value
   End Sub

   Public Overrides Function Sum(ByVal value As IConvertible) As IConvertible
       Return (Me.Value.ToDecimal(CultureInfo.CurrentCulture) + value.ToDecimal(CultureInfo.CurrentCulture))
   End Function

   Public Function ToInt32() As NumberInt
       Return New NumberInt(Me.Value.ToInt32(CultureInfo.CurrentCulture))
   End Function

   Public Function ToDecimal() As NumberDec
       Return New NumberDec(Me.Value.ToDecimal(CultureInfo.CurrentCulture))
   End Function

   Private Function IsNumericTypeCode(ByVal value As IConvertible) As Boolean

       Select Case value.GetTypeCode
           Case TypeCode.SByte, TypeCode.Byte, TypeCode.Int16, TypeCode.UInt16,
                TypeCode.Int32, TypeCode.UInt32, TypeCode.Int64, TypeCode.UInt64,
                TypeCode.Single, TypeCode.Double, TypeCode.Decimal
               Return True

           Case Else
               Return False
       End Select

   End Function

End Class


Saludos.








n-utz

Gracias por tomarte todo el tiempo para hacer eso, la verdad me ayuda mucho.

Tengo en claro lo que es el polimorfismo, sé que también se puede implementar con interfaces y demás.

Mirá capaz te pregunto algo que me deja en ridículo, pero me cuesta entender ciertas partes de lo que sería la sintaxis del lenguaje el cual posteaste, yo debo hacerlo en C#.

Pero en los métodos de Sum lo que estás haciendo es pasarle una variable digamos de cualquier tipo, que este será definido en cuánto llames a la función no? Y así lo convierte al tipo del colaborador interno de la clase de dónde fue llamada, cierto?

Me cuesta expresarme en objetos, lo que quiero decir es que cuando llamaría a Sum desde la clase derivada NumberDec ingresaría una variable de tipo Integer en mi caso (centrandome en mi problema de dominio) y este la parsearía a Decimal, y así retornaría el valor de la suma sin problemas.

Esta solución la pensé, aunque admito que me abriste la cabeza en cuánto a la implementación, también era una nebulosa.

La verdad que lo voy a resolver así, mañana tengo otra clase en la cuál va a plantear la solución y te la voy a comentar, para que finalmente puedas ver si era esto lo que pedía, que me parece que no, pero me gusta como alternativa.

Es un curso demasiado interesante que nos enseña a pensar como si todo se tratara de objetos enviando mensajes, y todo fuese simplemente eso. Nos enseña en SmallTalk y nosotros lo explayamos en diferentes lenguajes, en mi caso C#.

Gracias por tu tiempo Elektro, seguramente mañana te postee la solución, igualmente me ayudaste demasiado, un abrazo!