Howdy everyone. I've been messing around with some...
# cfml-general
j
Howdy everyone. I've been messing around with some oop stuff and ran into something that has me scratching my head. I can successfully call a static method from a class without instantiating an object of that class as advertised. However, whenever I try to call a static method from an abstract class, CF blows up and states that it can't create the abstract component. This is confusing to me since I'm calling a static function which by definition shouldn't need to create an instance. So calling a static method works until I define the class I'm calling it from as abstract. Not sure what I'm missing.
b
Probably just a bug. I'd enter a ticket 🙂
👍 1
You didn't specify if this was Adobe CF or Lucee or what version.
j
Happening for both ACF and Lucee.
z
have you tried lucee 5.3.10.84 it contains some more static fixes
👍 1
j
ACF 2021 Update 5. Lucee 5.3.9
I haven't! I'll give 5.3.10.84 a shot.
a
Happening for both ACF and Lucee.
Ugh.
states that it can't create the abstract component
Double ugh
b
I'm not too surprised. Both static and abstract are fairly recent features which underwent very little public testing and don't get used that much.
a
Confirmed I am seeing same as Joe:
Copy code
// AbstractBase.cfc
abstract component {

    public static function f(){
        return "hi"
    }

}
Copy code
// testAbstractBase.cfm
writeOutput(AbstractBase::f())
If I create a ConcreteImplementation.cfc and extend AbstractBase and call
ConcreteImplementation::f()
it works fine
👍 1
j
Just tried Lucee 5.3.10.84 and it has the same issue still.
👍 1
Ok. Thanks all. I guess I'll submit some tickets!
1
a
I'm just glad to see a CFMLer using (or at least trying to...) abstract and static functionality.
j
Well, I've been walking through the examples in Kent Beck's Test Driven Development and was doing just fine using CF and Testbox to recreate them. That is until one example called a static method from an abstract class lol.
c
From the Adobe docs: https://helpx.adobe.com/coldfusion/developing-applications/building-blocks-of-coldfusion-applications/object-oriented-programming-coldfusion.html
An abstract component can have abstract method without body and can also have methods with implementation.
Use the abstract keyword to create an abstract component and method. In ColdFusion, you cannot instantiate an abstract component. An abstract component is mostly used to provide base for sub-components. The first concrete component should have the implementation of all the abstract methods in its inheritance hierarchy.
I only remembered this because it came up in the "Adobe Certified Professional: Adobe ColdFusion" certification test.
s
@cfvonner Not sure how that doc is relevant here? Static methods don't (shouldn't!) require instantiating the class. ACF (and Lucee) are just broken here.
(I mean, this isn't surprising, CFML's attempts to imitate other OOP languages are often broken 😞 )
👀 1
(I think most people know my feelings about Adobe's obsession with adding Java-like features to CFML 🙂 )
👍 1
c
I was just referring to the issue of not being able to instantiate an abstract component. It was not entirely clear to me which of the issues mentioned above was the "bug" - if it was that an abstract component couldn't be instantiated, then it is behaving as designed. If the bug was the issue with the combination of "static" methods and "abstract" components, then I guess it isn't relevant. Is it common in the non-CFML world to use "abstract" classes that contain "static" methods that are intended to be called without instantiating the class?
b
Static methods are, by definition, called without instantiating the class. So that's sort of a self-answering question 🙂
The abstract docs above are just a generic description of how abstract classes work in most classically OO languages. It doesn't mention the behavior of static methods because Adobe probably never thought through all that. But in any language I've seen that supports static methods, they are expected to work on any class regardless of whether its abstract or not.
👍 1
I'm sort of with Sean in regards to some of these Java-ish features in CFML. I appreciate and use them when I write Java code, but I've never felt like they were a great fit in CFML as a language, nor did I see a huge demand or use case for them outside of the "let's make ourselves a 'real' language" sort of push. which started as copying Java features, and of late has moved more to copying JS features 😆
😂 1
z
IMHO it's completely bullshit and not CFML-y that with statics that you need to reboot or touch a file to pick up changes. I will die in this hill
c
@bdw429s that's good info. As someone who has never done OO programming outside of CFML, I plead ignorance to how "static" is supposed to work in the wider world. The only Adobe doc that references static in CFCs that I could find was: https://helpx.adobe.com/coldfusion/developing-applications/building-blocks-of-coldfu[…]-and-using-coldfusion-components/cfc-variables-and-scope.html There is one example of calling a static method on a CFC without instantiating it (see Case3.cfc/Case3.cfm). It took me a couple passes of that page to notice that the calling code wasn't instantiating the compoent first:
Case3::splitFullName("John Doe"))
Based on the limited amount of CFML documentation available, it isn't clear to me what problem "static" functions are trying to solve. I think I understand the value of "static" variables, but not really getting the "static" functions.
It appears that Ortus' Modern CFML book does a better job of explaining it's utility: https://modern-cfml.ortusbooks.com/cfml-language/components/static-constructs
b
Static makes more sense to me in Java since a Class is an object of its own produced by a classloader. In CFML, a CFC name is just a string defining where on disk you may find a CFC if you wanted to look for it. Static members/methods are widely used in java to enforce a singleton pattern, using the class's static data as the "holding" pen for the singleton instance. Furthermore, it's common to see pure utility methods that require no state (like
Math.round( float a )
to be a static method so you can just import the class and call it directly.
In a CFML context however, using an IOC container, it's the same for me to just have (to borrow the same example) Math.cfc
Copy code
component singleton {
  function round( a ){ ... }
}
and then
Copy code
property name='Math' inject;

...

Math.round( foo )
I don't really _nee_d anything to be static for that to work, I don't have to worry about instantiation due to the IOC container, and there's no real performance overhead since it's still a singleton and not re-created everywhere.
It's a bit more compelling to have static data inside of a transient that I don't want created for every instance such as LogBox log levels...
Copy code
this.OFF   = -1;
	this.FATAL = 0;
	this.ERROR = 1;
	this.WARN  = 2;
	<http://this.INFO|this.INFO>  = 3;
	this.DEBUG = 4;
However it feels a bit like a micro-optimization in CFML to worry about a few Bytes here and there in a language which already significantly expands the memory overhead for a single class instance.
a
I find (final) static properties useful, and occasionally static methods. Although I will say with the latter it's mostly been when I need to circumvent CFWheels object-instantiation shitfuckery, rather than any masterful design on my part. As far as abstract stuff goes... not something I use that often but I figure better to have and not need, than need and not have. If I was in the habit of building general libraries intended to be used by third parties, I'd probably want to stick to familiar OOP concepts for the same reason I'd stick to familiar design patterns: it communicates intent in a generally understood way (*). Given CF supports default implementations on interface methods, abstract seems to be a bit of a lemon though, dunnit? They're kinda two ways of skinning the same cat? And designing-to-an-interface is more zeitgeisty than overbaking inheritance, I think. (*) this is a theory that collapses pretty quickly in the CFML world, granted. But I think this is more a shortcoming of the CFML world than the industry-accepted approaches, I think.
👍 1
Good examples there @bdw429s, Although I would never consider it a issue of optimisation; it's just one of clarity-of-intent of the code. People expect consts (final static in CFML) like that. Same with like HTTP status codes etc
👍 1
I am divided on "the CFML community is still a bit MyWebPage.cfm" as being a rationale to abandon efforts to enable some CFML code to be written well and clearly and in an OOP fashion. "In an OOP fashion" doesn't have to be pushed all the way to "Java Enterprise Horror", which is a cheap cop out ppl often fall back on.
However sometimes I do go "oh fuck the lot of ya... go back and play with ya
<cftagisland>
then".
😆 2
s
It's fine to take inspiration from other languages but Adobe's main problem is that they're usually tried to copy features from Java/Script and just get it wrong and don't even think about whether it makes any sense to have said features in a dynamically typed, compile-on-demand language.
z
reckon we can still accommodate everyone
s
We have
onMissingMethod()
because I pushed for it -- because Ruby and Smalltalk have something very similar. And that makes sense in a dynamic OOP language.
I agree with Adam that interface + concrete class is "better" and we don't need the complexity of abstract classes (and really shouldn't be using them). But the lack of OOP exposure most CFers have means that they'll ask for features from Java/Script without even understanding the feature and, like Adobe, having no idea how/whether it fits with a dynamic OOP language.
3
We got covariance in overriding but Adobe implemented it incorrectly (I think they've partially fixed it now -- but several aspects of overriding are still broken). They completely half-assed interface implementation checking (and it's still broken). So many of the Java-in-CF features are poorly implemented or outright broken.
z
the static inheritance problem in lucee was fixed in 5.3.10.81 https://luceeserver.atlassian.net/browse/LDEV-4212
s
@zackster No one is talking about "static inheritance".
z
until it bytes (sic) them in the bum, i figure such information is useful to share isn't it?
j
Posted the issue in the Lucee forum here - https://dev.lucee.org/t/static-methods-failing-when-called-from-an-abstract-class/11292 - before submitting a bug as requested in the instructions found here. I don't use Lucee and have not been involved in the Lucee community so not sure where to go from here, but I assume I'll receive direction in replies to my post.
z
I check the lucee jira too, feel free to file a bug
👍 1
j
Thanks, @zackster. Bug filed.
z
cheerz