Import Class Conditionally with the Keyword 'Use'

Import class conditionally with the keyword 'use'

The only thing use does is to alias a class name. That's it. Nothing more.

Instead of having to repeatedly write the fully qualified classname in your script:

$q = new \Foo\Bar\Baz\Quux;
if ($q instanceof \Foo\Bar\Baz\Quux) ...

You can shorten that to:

use Foo\Bar\Baz\Quux;

$q = new Quux;
if ($q instanceof Quux) ...

As such, it makes absolutely no sense to want to use use conditionally. It's just a syntactic helper; if it could be used conditionally your script syntax would become ambiguous, which is something nobody wants.

It doesn't reduce code loading, because code is only loaded explicitly by require/include calls or via autoloading. The latter one is greatly preferred, since it already lazily springs into action only when needed.

Using namespace in if / else statements

Please see Scoping rules for importing

The use keyword must be declared in the outermost scope of a file (the global scope) or inside namespace declarations. This is because the importing is done at compile time and not runtime, so it cannot be block scoped.

All use does is import a symbol name into the current namespace. I would just omit the import and use the fully qualified class name, eg

switch ($api) {
case 'foo' :
require_once('foo.php');
$someVar = new SomeClass();
break;
case 'bar' :
require_once('bar.php');
$someVar = new \xxxx\TheClass();
break;
default :
throw new UnexpectedValueException($api);
}

You can also simply add the use statement to the top of your script. Adding it does not commit you to including any files and it does not require the symbol to be known, eg

use xxxx\TheClass;

switch ($api) {
case 'foo' :
require_once('foo.php');
$someVar = new SomeClass();
break;
case 'bar' :
require_once('bar.php');
$someVar = new TheClass(); // imported above
break;
default :
throw new UnexpectedValueException($api);
}

Conditional Inheritance neglects changed condition in workspace in python

Explanation

Python import works as follows:

  • It executes the code in the module
  • Symbols created by executing the module code are placed in the module symbol table (including class C)
  • import only loads a module once (i.e. the module is cache) for a process. Thus, subsequent imports of the same module has no effect.
  • Consequently, the definition for class C is placed in the module symbol table on the first import. Changing cond after the import thus has no affect on the definition.
  • Use reload to force the reload of a module (i.e. not using the cache version).

Sharging global variables across modules

  • A suggested approach is the place the global shared variables in a config module

Considering the above the following code works.

Code

config.py (contains globals to share across modules)

cond = True

test_abc.py (contains the definition of classes a, b, c)

import config

class A():
def __init__(self, x):
self.x = x

def getX(self):
return f"A {self.x}"

class B():
def __init__(self, x):
self.x = x

def getX(self):
return f"B {self.x}"

# inherits from A or B
class C(A if config.cond else B):
def __init__(self, x):
super().__init__(x)

main.py (main program)

from importlib import reload             # Allows reloading of modules
import config # place variables we want to share across modules

# Test with cond = True
config.cond = True # Use True in condition for inheritance
import test_abc # Use import first time, can reload on subsequent calls
ca = test_abc.C(1)
print("First call: ", ca.getX()) # Test that we obtain A object

# Test with cond = False
config.cond = False
reload(test_abc) # reload module

ca = test_abc.C(1)
print("Second call:", ca.getX()) # Test that we obtained B object

Output

First call:  A 1
Second call: B 1

How does the keyword use work in PHP and can I import classes with it?

use doesn't include anything. It just imports the specified namespace (or class) to the current scope

If you want the classes to be autoloaded - read about autoloading

is it possible to use conditional import and part-of with Dart?

No. Conditional imports (and exports) are only allowed on imports and exports.
A part declaration cannot be conditional.

What you can do is to let the implementation of _method come from a top-level function:

import "src/default.dart" 
if (dart.library.io) "src/io.dart"
if (dart.library.html) "src/web.dart"
as impl;

class Foo {
factory Foo() = impl.Bar;
void _method() => impl.fooMethod(this);
}

and then, e.g., src/io.dart can be:

import "../foo.dart";
class Bar extends Foo {
void _barMethod() => io.something;
}
void fooMethod(Foo foo) => (foo as Bar)._barMethod();

That way you can abstract the implementation of the private method into a separate library.

Conditionally including code based on the existence of a class

Typically, situations like this are much better handled via Inversion of Control than trying to determine the existence of a class.

Instead of looking for "ClassA" and "ClassB", it would be a better option to provide 2 interfaces that could be implemented. You could then use Dependency Injection to attempt to inject an instance of IInterfaceA, and if it fails, use an instance of IInterfaceB instead.

A good articles to read might be Martin Fowler's article on IoC. Also, you may want to look at the Managed Extensibility Framework (now included in .NET 4) which makes this very easy in C#.

How can I conditionally make a class use a trait if it exists?

Your question is fun, and eval() likely meets your needs. This style using code generation is ugly, but I know it works because I verified it myself on my own machine. Here's how you can do it:

$src = '
class foo {
var $bar; // and all of your other code goes here
';
if (file_exists('myTrait.php')) {
include_once('myTrait.php');
$src .= "use myTrait;\n";
}
$src .= "}";
eval ($src); // your class finally gets declared

I don't use eval() often, but it's fun when it solves a problem that otherwise cannot be conventionally solved.

How can I conditionally import an ES6 module?

We do have dynamic imports proposal now with ECMA. This is in stage 3. This is also available as babel-preset.

Following is way to do conditional rendering as per your case.

if (condition) {
import('something')
.then((something) => {
console.log(something.something);
});
}

This basically returns a promise. Resolution of promise is expected to have the module. The proposal also have other features like multiple dynamic imports, default imports, js file import etc. You can find more information about dynamic imports here.



Related Topics



Leave a reply



Submit