public function bind($abstract, $concrete = null, $shared = false)
        {
            // If the given type is actually an array, we'll assume an alias is being
            // defined and will grab the real abstract class name and register the
            // alias with the container so it can be used as a short-cut for it.
            if (is_array($abstract)) {
                list($abstract, $alias) = $this->extractAlias($abstract);
                $this->alias($abstract, $alias);
            }

            // If no concrete type was given, we will simply set the concrete type to
            // the abstract. This allows concrete types to be registered as shared
            // without being made state their classes in both of the parameters.
            if (is_null($concrete)) {
                $concrete = $abstract;
            }

            // If the factory is not a Closure, it means it is just a class name that
            // is bound into the container to an abstract type and we'll just wrap
            // it up in a Closure to make things more convenient when extending.
            if (!$concrete instanceof \Closure) {
                $concrete = function($c) use ($abstract, $concrete) {
                    $method = ($abstract == $concrete) ? 'build' : 'make';
                    return $c->$method($concrete);
                };
            }

            $this->bindings[$abstract] = compact('concrete', 'shared');
        }