As I've been working with AS I've developed a collection of utility functions. For example:
$ cat utils/curried.as
package utils {
public function curried(f:Function, ...boundArgs):Function {
function curriedHelper(...dynamicArgs):* {
return f.apply(null, boundArgs.concat(dynamicArgs));
}
return curriedHelper;
}
}
And I've found that, some times, I want to keep more than one public function in each file... But ActionScript restricts me to one public definition per file, if that file defines its self as being part of a package.
So, without creating a class with static methods, how could I get more than one public function in a single .as file?
simply put, you can't ... for a package level function declaration, you need one file per declared function ...
little side note: personally, i'd go Josh's way and stuff them into a class ... i think allowing function level declarations at all was simply to have a bit more backward compatibility to AS2 ... it's ok, for prototyping or things that'll never leave your hands ... but you imagine relying on 3-4 libraries, each exposing their functionality through package level functions? firstly, it completely spams your autocompletion (if your IDE offers one), and secondly, you always need to look at the imports to see which function comes from where ... the prefix you mentioned is actually of great advantage ... but ok, that's my opinion ...
greetz
back2dos
Related
The project I am on is having horrible problems with class collisions in the classpath and developers reusing class names. For example, we have 16, yes 16 interfaces called Constants in this bloody thing and its causing all kinds of problems.
I want to implement a checkstyle check that will search for various forms of class duplication. here's the class
import java.io.File;
import java.util.List;
import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
import com.wps.codetools.common.classpath.ClassScanner;
import com.wps.codetools.common.classpath.criteria.ClassNameCriteria;
import com.wps.codetools.common.classpath.locator.ClasspathClassLocator;
/**
* This codestyle check is designed to scan the project for duplicate class names
* This is being done because it is common that if a class name matches a class
* name that is in a library, the two can be confused. Its in my best practice that
* the class names should be unique to the project.
*
*
*/
public class DuplicateClassNames extends AbstractFileSetCheck {
private int fileCount;
#Override
public void beginProcessing(String aCharset) {
super.beginProcessing(aCharset);
// reset the file count
this.fileCount = 0;
}
#Override
public void processFiltered(File file, List<String> aLines) {
this.fileCount++;
System.out.println(file.getPath());
ClassScanner scanner = new ClassScanner();
scanner.addClassCriteria(new ClassNameCriteria(file.getPath()));
scanner.addClassLocater(new ClasspathClassLocator());
List<Class<?>> classes = scanner.findClasses();
if (classes.size() > 0) {
// log the message
log(0, "wps.duplicate.class.name", classes.size(), classes);
// you can call log() multiple times to flag multiple
// errors in the same file
}
}
}
Ok, so the ClassScanner opens up the classpath of the current JVM and searches it with various criteria. This particular one is a class name. It can go into the source folders, and most importantly it can go into the libraries contained in the classpath and search the *.class files within the jar using ASM. If it finds copies based on the criteria objects that are presented, it returns an array of the files. This still needs some massaging before mainstream but im on a time budget here so quick and dirty it goes.
My problem is understanding the input parameters for the check itself. I copied from the example, but it looks like CheckStyles is giving me a basic IO file object for the source file itself, and the contents of the source file in a string array.
Do I have to run this array thru another processor before I can get the fully qualified class name?
This is more difficult to do right than one might think, mostly because Java supports all kinds of nesting, like static classes defined within an interface, anonymous inner classes, and so on. Also, you are extending AbstractFileSetCheck, which is not a TreeWalker module, so you don't get an AST. If you want an AST, extend Check instead.
Since "quick and dirty" is an option for you, you could simply deduce the class name from the file name: Determine the canonical path, remove common directories from the beginning of the String, replace slashes with dots, cut off the file extension, and you are more or less there. (Without supporting inner classes etc. of course.)
A better solution might be to extend Check and register for PACKAGE_DEF, CLASS_DEF, ANNOTATION_DEF, ENUM_DEF, and INTERFACE_DEF. In your check, you maintain a stack of IDENTs found at these locations, which gives you all fully qualified class names in the .java file. (If you want anonymous classes, too, also register for LITERAL_NEW. I believe in your case you don't want those.)
The latter solution would not work well in an IDE like Eclipse, because the Check lifecycle is too short, and you would keep losing the list of fully qualified class names. It will work in a continuous integration system or other form of external run, though. It is important that the static reference to the class list that you're maintaining is retained between check runs. If you need Eclipse support, you would have to add something to your Eclipse plugin that can keep the list (and also the list from previous full builds, persisted somewhere).
im using Adobe® Flash® Builder™ 4.6,the problem also exist in previous versions.
for some reason ,i am using
cls = applicationDomain.getDefinition(name) as Class;
to get the object's constructor and then create the instance of my modules class.thus make compile ignore my module classes ,because they are not related from my main class.how to force else classes also compiled into my swf or swc file? i didn't find where i can adjust my compile option.
by now i use this way to solve my problem,at the very beginning of the program entry.
if(1+1==3){
//never be run but do make classes merge into swf files.
new MyModule();
}
i have hundreds of modules like this one,i do hope i can find a way to solve this problem permanently
You can try with this
package
{
public class IncludeClasses
{
import com.abc.db.Database;Database;
import com.abc.logs.RemoteLogTarget; RemoteLogTarget;
import com.abc.logs.LocalLogTarget; LocalLogTarget;
import com.abc.exception.GlobalExceptionHandler; GlobalExceptionHandler;
import com.abc.utils.NetConnectionMonitor;NetConnectionMonitor;
}
}
You need to use the class to get it to compile in the swf.
Not the best method but
private var someVar:someClass;
Using the "new" keyword will cause the run-time to allocate memory for the object so you don't want to use that.
This whole loading modules and compiling classes has a code smell to it.
You would be better off having your classes in the modules implement an interface.
You need at least one strict reference to your class to appear within the project. I use a static variable of type Array to stuff all of the classes I need, and never really reference that array, if I can.
private static var dummy:Array=[OneClass, AnotherClass, Class01, Etc];
You can also do this by setting your compiler flag.
About the application compiler options
See:
include-libraries library [...]
Include only classes that are inheritance dependencies of classes that
are included with the include-classes compiler option.
The default value is false.
This is an advanced option. You might use this compiler option if you
are creating a custom RSL and want to externalize as many classes as
possible. For example:
compc -include-classes mx.collections.ListCollectionView
-include-inheritance-dependencies-only=true
-source-path . -output lcv2 -directory
Say I have the following set up of classes...
Road - extends MovieClip Car - extends Road
Controller - extends Car
And I want to incorporate some common Mathematical functions in them all to make them faster e.g.(replacing Math classes with some speedy bitwise versions).
What is the best way to incorporate these functions into all of them without writing the functions in the classes or extending from class of the functions. Is importing the class into each the fastest way or is their a better way?
You can create a public function that you can import into any class. Some examples in the base language are navigateToURL() and getTimer(). These are just public functions in a package, not classes.
So create a public function like so
package nameOfYourPackage{
public function doSomething(a:arguments):returnType
{
// Stuf the function does goes here;
}
}
then you can import it into any class like so:
import nameOfYourPackage.doSomething;
and then youc an call it anywhere in a class that imports it as:
doSomething(args);
I agree with the comments that your design may needs some work. You can't use a Class in another Class without an import statement that refers to it in some way--even if you're just importing an Interface that the Class implements.
The most flexible way to handle this is to have the functional object be passed in to the object that needs it, rather than having that object create the instance itself. This will allow you to swap out a different implementation when you need to (for instance, you might want to use a mock instance for unit testing, or you might need slightly different functionality optimized for a mobile device).
You can pass in the instance either in the Constructor or use a property (which would allow you the freedom to change out the implementation at runtime).
I currently pass a reference to my model through the constructor to any class that needs it in my simple mvc pattern, this can get annoying at times when it starts to go deeper.
How do Classes such as LoadMax allow you from anywhere to simple import the class, and do something like addChild(LoaderMax.getContent("bg"));? Replicating this should surely be a good way to have my model work, without the complexity of big frameworks?
Statics are your friend
As previous answers have noted, TweenLite/Max etc. makes heavy use of static members to get work done. This is exactly like the Math class, for example, and can be a very convenient design pattern. You have global access to the class, and that can definitely alleviate the issue of getting access to variables through deeply nested classes.
Statics are the enemy
Statics, however, bring certain problems to the table. Most importantly, they tend to reduce flexibility and modularity of classes through the often unnecessary addition of tightly coupled relationships. It's a bit like pouring concrete over your application. It does work, but changing behavior becomes difficult as project features change.
Static members != instance members
Note, very clearly, that a static member "belongs" to the class itself, and not an instance of that class. Static members have no access to instance members. This causes troubles when you want to mix these members up in logic. You tend to have to make everything static (the so-called "static-cling" effect). Static patterns are often argued to be argued to be "anti" object-oriented, for precisely this reason. Once you build a structure on a static pattern you tend to lose many of the principles that makes OOD powerful.
In small does, they're pretty nice
That all being said - TweenLite is a great example of a static pattern that is totally appropriate - its a utility package, one that logic is not dependent on. And that should probably be how you leverage statics, too.
To reduce reliance on statics, or even global vars, it does often mean writing more code, but the flexibility in app structure gained is often quite worth it. #Marty_Wallace has a pretty good solution imo.
Demeter and the Paperboy
Finally, I'll just mention the Law of Demeter, or the Principle of Least Knowledge, and the related Paperboy and the Wallet example, which is often pointed to in discussions of statics:
Each unit should have only limited knowledge about other units: only
units "closely" related to the current
unit.
Each unit should only talk to its friends; don't talk to strangers.
Only talk to your immediate friends.
Hopefully that sheds a little bit of light on a fairly complicated and not-often obvious issue.
This is done using the static namespace, however I discourage the use of this.
package
{
public class Main
{
public static function sayHell():void
{
trace("hello!");
}
}
}
You can now call sayHello() like this from anywhere in the application (assuming you've imported the class).
Main.sayHello();
Another thing you can do (to make the entire class accessible from within the application) is create a static property that refers to the class itself:
package
{
public class Something
{
public static var instance:Something;
public function Something()
{
instance = this;
}
public function someFunction():void
{
trace('hello!');
}
}
}
Which you can now use like so:
Something.instance.someFunction();
The only thing to note here is that you need to create an instance of Something for this to work to call the constructor and define instance.
What I would do
Create a base class for all objects in your application
Create a manager class that takes care of these objects
Create a setter within your base class to define the manager
Here's an example:
Base
package
{
public class Base extends Object
{
private var _manager:Manager;
public function set manager(m:Manager):void
{
_manager = m;
init();
}
protected function init():void
{
manager.someFunction();
}
public function get manager():Manager{ return _manager; }
}
}
Manager
package
{
public class Manager extends Object
{
public function someFunction():void
{
trace('hello!');
}
}
}
Now anything that extends Base will have access to anything held in Manager via the manager getter property. All you need to do is make sure you define the manager, which is easily achieved from within anything that extends Base like so:
var something:SomeExtendingClass = new SomeExtendingClass();
something.manager = manager;
The example you gave is just a static method, but to answer your question about a global instance of a class:
package myPackage
{
public var globalVariable:MyClass = new MyClass();
}
You can access it with:
import myPackage.globalVariable;
trace(globalVariable);
I think you have to rethink in which way you want to name your classes.
You can instantiate whatever class you want, at run-time, but to access a instance by name, you have to make changes in your structure. For example, the getContent() function you mentioned in LoaderMax, all it does is to search in an array for the given loader that matchs the name, among other things. You can read the name variable comment for a description.
A name that you use to identify the loader instance. This name can be fed to the getLoader() or getContent() methods or traced at any time. Each loader's name should be unique. If you don't define one, a unique name will be created automatically, like "loader21".
So in this system, you have to name every single member (loaders in this case) if you want to be able to search them. Because if I call getClassInstance("myinstance"), what is "myinstance" representing? Where should I name it?
That said, if you want to do it for DisplayObjects only, you can use getChildByName. But again, you have to name every DisplayObject (just set the name variable).
Hope this helps.
As we all know, when we derive a class and use polymorphism, someone, somewhere needs to know what class to instanciate. We can use factories, a big switch statement, if-else-if, etc. I just learnt from Bill K this is called Dependency Injection.
My Question: Is it good practice to use reflection and attributes as the dependency injection mechanism? That way, the list gets populated dynamically as we add new types.
Here is an example. Please no comment about how loading images can be done other ways, we know.
Suppose we have the following IImageFileFormat interface:
public interface IImageFileFormat
{
string[] SupportedFormats { get; };
Image Load(string fileName);
void Save(Image image, string fileName);
}
Different classes will implement this interface:
[FileFormat]
public class BmpFileFormat : IImageFileFormat { ... }
[FileFormat]
public class JpegFileFormat : IImageFileFormat { ... }
When a file needs to be loaded or saved, a manager needs to iterate through all known loader and call the Load()/Save() from the appropriate instance depending on their SupportedExtensions.
class ImageLoader
{
public Image Load(string fileName)
{
return FindFormat(fileName).Load(fileName);
}
public void Save(Image image, string fileName)
{
FindFormat(fileName).Save(image, fileName);
}
IImageFileFormat FindFormat(string fileName)
{
string extension = Path.GetExtension(fileName);
return formats.First(f => f.SupportedExtensions.Contains(extension));
}
private List<IImageFileFormat> formats;
}
I guess the important point here is whether the list of available loader (formats) should be populated by hand or using reflection.
By hand:
public ImageLoader()
{
formats = new List<IImageFileFormat>();
formats.Add(new BmpFileFormat());
formats.Add(new JpegFileFormat());
}
By reflection:
public ImageLoader()
{
formats = new List<IImageFileFormat>();
foreach(Type type in Assembly.GetExecutingAssembly().GetTypes())
{
if(type.GetCustomAttributes(typeof(FileFormatAttribute), false).Length > 0)
{
formats.Add(Activator.CreateInstance(type))
}
}
}
I sometimes use the later and it never occured to me that it could be a very bad idea. Yes, adding new classes is easy, but the mechanic registering those same classes is harder to grasp and therefore maintain than a simple coded-by-hand list.
Please discuss.
My personal preference is neither - when there is a mapping of classes to some arbitrary string, a configuration file is the place to do it IMHO. This way, you never need to modify the code - especially if you use a dynamic loading mechanism to add new dynamic libraries.
In general, I always prefer some method that allows me to write code once as much as possible - both your methods require altering already-written/built/deployed code (since your reflection route makes no provision for adding file format loaders in new DLLs).
Edit by Coincoin:
Reflection approach could be effectively combined with configuration files to locate the implmentations to be injected.
The type could be declared explicitely in the config file using canonical names, similar to MSBuild <UsingTask>
The config could locate the assemblies, but then we have to inject all matching types, ala Microsoft Visual Studio Packages.
Any other mechanism to match a value or set of condition to the needed type.
My vote is that the reflection method is nicer. With that method, adding a new file format only modifies one part of the code - the place where you define the class to handle the file format. Without reflection, you'll have to remember to modify the other class, the ImageLoader, as well
Isn't this pretty much what the Dependency Injection pattern is all about?
If you can isolate the dependencies then the mechanics will almost certainly be reflection based, but it will be configuration file driven so the messiness of the reflection can be pretty well encapsulated and isolated.
I believe with DI you simply say I need an object of type <interface> with some other parameters, and the DI system returns an object to you that satisfies your conditions.
This goes together with IoC (Inversion of Control) where the object being supplied may need something else, so that other thing is automatically created and installed into your object (being created by DI) before it's returned to the user.
I know this borders on the "no comment about loading images other ways", but why not just flip your dependencies -- rather than have ImageLoader depend on ImageFileFormats, have each IImageFileFormat depend on an ImageLoader? You'll gain a few things out of this:
Each time you add a new IImageFileFormat, you won't need to make any changes anywhere else (and you won't have to use reflection, either)
If you take it one step further and abstract ImageLoader, you can mock it in Unit Tests, making testing the concrete implementations of each IImageFileFormat that much easier
In vb.net, if all the image loaders will be in the same assembly, one could use partial classes and events to achieve the desired effect (have a class whose purpose is to fire an event when the image loaders should register themselves; each file containing image loaders can have use a "partial class" to add another event handler to that class); C# doesn't have a direct equivalent to vb.net's WithEvents syntax, but I suspect partial classes are a limited mechanism for achieving the same thing.