Различное поведение функции при различных типах аргумента

Предположим нам необходимо различное поведение функции в зависимости от типа получаемого аргумента. Реализуется несколькими способоми. 1ый кажется самый простой для восприятия, а возможно и самый быстрый.

package ;

import flash.display.Shape;

import Type;

class Main
{
        static public function main()
        {
                f(true);
                f(12345);
                f(1.2345);
                f("abcdef");
                f(new Shape());
                f(f);
                f({name: "abcdef" } );
                f(null);
        }
       
        static public function f(value:Dynamic)
        {
                //1) Рабочий вариант на switch
                switch(Std.string(Type.typeof(value)))
                {
                        case "TBool":                           trace("I am Bool");
                        case "TInt":                            trace("I am Int");
                        case "TFloat":                          trace("I am Float");
                        case "TClass([class String])":          trace("I am String");
                        case "TClass([class Shape])":           trace("I am Shape");
                        case "TFunction":                       trace("I am Function");
                        case "TObject":                         trace("I am Object");
                        case "TNull":                           trace("I am Null");
                }
               
                //2) Рабочий вариант на if
                if (Std.is(value, Bool))                trace("I am Bool");
                else if (Std.is(value, Int))            trace("I am Int");
                else if (Std.is(value, Float))          trace("I am Float");
                else if (Std.is(value, String))         trace("I am String");
                else if (Std.is(value, Shape))          trace("I am Shape");
                else if (Reflect.isFunction(value))     trace("I am Function");
                else if (Reflect.isObject(value))       trace("I am Object");
                else if (value == null)                 trace("I am Null");

                //3) Рабочий вариант на if
                if (Type.enumEq(Type.typeof(value), ValueType.TBool))                           trace("I am Bool");
                else if (Type.enumEq(Type.typeof(value), ValueType.TInt))                       trace("I am Int");
                else if (Type.enumEq(Type.typeof(value), ValueType.TFloat))                     trace("I am Float");
                else if (Type.enumEq(Type.typeof(value), ValueType.TClass(String)))             trace("I am String");
                else if (Type.enumEq(Type.typeof(value), ValueType.TClass(Shape)))              trace("I am Shape");
                else if (Type.enmEq(Type.typeof(value), ValueType.TFunction))                   trace("I am Function");
                else if (Type.enumEq(Type.typeof(value), ValueType.TObject))                    trace("I am Object");
                else if (Type.enumEq(Type.typeof(value), ValueType.TNull))                      trace("I am Null");
        }
}