aliaspooryorik
aliaspooryorik
aliaspooryorik
// base class
component {
function ready() {
return true;
}
}
aliaspooryorik
aliaspooryorik
// foo
component extends="base" {
function ready() {
return false;
}
}
// bar
component extends="base" {
// no ready function as want it to return true
}
aliaspooryorik
aliaspooryorik
super.whatever()
and then specialises. I just don't think you should use inheritance to give default behaviour with the expectation a subclass doesn't event call the parent methodwebsolete
09/09/2024, 4:48 PMsknowlton
09/09/2024, 4:48 PMsuper.whatever()
) but if you're fully overriding it, your inheritance model is inaccurate (e.g. maybe you need an extra layer where foo descends from a simpler version that doesn't have ready())websolete
09/09/2024, 4:49 PMwebsolete
09/09/2024, 4:50 PMsknowlton
09/09/2024, 4:51 PMsknowlton
09/09/2024, 4:51 PMaliaspooryorik
aliaspooryorik
aliaspooryorik
websolete
09/09/2024, 4:53 PMsknowlton
09/09/2024, 4:53 PMsknowlton
09/09/2024, 4:54 PMwebsolete
09/09/2024, 4:54 PMaliaspooryorik
Dave Merrill
09/09/2024, 6:06 PMwebsolete
09/09/2024, 6:09 PMaliaspooryorik
aliaspooryorik
aliaspooryorik
super
and one that does not call super
at all. It is the latter I object to @Dave Merrillbdw429s
09/09/2024, 6:23 PMreturn "woof";
and you override the Chihuahua
class only to have an implementation of return "Yip"
, leaving all other dog classes to use the default, then I see no issue. This is a perfectly valid OO use case of inheritance and method overriding to provide a customized behavior for one subclass, while other sub classes can use the default. So long as your overridden methods implement the correct method contract, you should be fine.
But I don't know if that's your exact scenario, which is where some pragmatism should be used. Your example is just a boolean, and if the real use case was more along the lines of a base class of Product
which contained a field of chargeTax
and defaulted to true, containing the getter and setter, and you wanted to simply turn off sales tax for certain products, I would be inclined to NOT override the getChargeTax()
getter, but to instead, simply set it off in my concrete constructor class
// PaperBackBook constructor
function init() {
super.init();
setChargeTax( false );
}
But, of course, this assumes a few things-- for starters that the base class is mutable! It also protects against code like variables.chargeTax
which may bypass the getters entirely!
I think all this stuff must be taken into account, and at the end of the day, there are prolly several "right" answers and potentially one or two "better" answers based on how your app is written and used.
Now to address this
> I think it makes the code less readable as by a function missing from the subclass I now need to go look at the parent to know what the heck it'll do
IMO, this is just because CF has terrible tooling 🙂 In Java, this would not be an issue as your intellisense would answer all those questions right there in the code. This is the sort of stuff we plan to get working n our BoxLang VSCode extension.denny
09/09/2024, 6:23 PMI just don't think you should use inheritance to give default behaviour with the expectation a subclass doesn't event call the parent methodMaybe I need more coffee but I think you only sometimes want to call the parent method? Basically what Dave said about the fields (loved the trains comment BTW 😃)… sometimes it makes sense to call it, sometimes it makes sense to "replace" or "totally override" it, I think?
websolete
09/09/2024, 6:28 PMDog.cfc
(base) that has a wagTail()
method, and you have a subclass BostonTerrier.cfc
that effectively has no tail to wag, then that method is invalid in the base and should be implemented only in those extended objects where it applies. correct @aliaspooryorik?denny
09/09/2024, 6:35 PMaliaspooryorik
aliaspooryorik
// BaseBankAccount - I am never called directly only subclasses are instantiated
class {
function getInterestRate() {
return 0;
}
}
// SaverBankAccount - I can be instantiated
class extends BaseBankAccount {
function getInterestRate() {
return 2;
}
}
// StudentBankAccount - I can be instantiated
class extends BaseBankAccount {
// there is no getInterestRate so BaseBankAccount.getInterestRate is used
// this is what I don't like
}
aliaspooryorik
aliaspooryorik
// BaseBankAccount - I am never called directly only subclasses are instantiated
class {
// there is no getInterestRate here as that is specific to each subclass
}
// SaverBankAccount - I can be instantiated
class extends BaseBankAccount {
function getInterestRate() {
return 2;
}
}
// StudentBankAccount - I can be instantiated
class extends BaseBankAccount {
function getInterestRate() {
return 0;
}
}
aliaspooryorik
aliaspooryorik
aliaspooryorik
websolete
09/09/2024, 6:45 PMbdw429s
09/09/2024, 6:45 PMabstract
modifier here, FWIW 🙂 Your example makes sense, and I would say I prolly disagree. So long as the default interest rate in the base class is valid, then I see no reason to add boilerplate and override it with the same value. Even more so, if the business wants to be able to change the default rate and have that change propagate instantly with a single line of code to all concrete classes not overriding. Your second example makes even less sense to me 🙂 I mean you could just return the super call, but again, that's just writing code for the sake of writing code.
The only scenario in which I wouldn't want the base class's method being called is if it had a dummy value like return -1
but in that case, you shouldn't; have put an implementation there, you should have made it an abstract method to enforce the override.
#TeamDontOverrideWhatYouDontNeedTodenny
09/09/2024, 6:48 PMStudentBankAccount
only needs to add things that aren't already in the base class, as that's one of the nicer bits about inheritancealiaspooryorik
abstract
or even private
on the base BaseBankAccount
class would do the trick - but obviously wouldn't run so I'm trying to show code that you might happen upon in a code base and if you'd like it or not (on the basis that the next person to maintain the code is a serial killer who knows where you live!)denny
09/09/2024, 6:51 PMdenny
09/09/2024, 6:54 PMaliaspooryorik
super
is just rubbish - so I'm going to delete that as it's far too simplistic for a use casebdw429s
09/09/2024, 7:18 PMbdw429s
09/09/2024, 7:19 PM// concrete classes will be required to implement me
abstract function myAbstractMethod()
denny
09/09/2024, 7:22 PMdenny
09/09/2024, 7:23 PMdenny
09/09/2024, 7:24 PMbdw429s
09/09/2024, 7:27 PMdenny
09/09/2024, 7:31 PMdenny
09/09/2024, 7:32 PMAdam Cameron
aliaspooryorik
aliaspooryorik
Adam Cameron
Inheritance for repeated functionality yes
Adam Cameron
aliaspooryorik
denny
09/10/2024, 9:28 AMUnsupportedOperationException
kinda for this…bkbk
09/10/2024, 9:36 PM