Feature request that'll never happen: Traits

i am not against traits, it may have a usecase for you.

i could say the same with “use”.

include 'TheWorldIsNotEnough_sayHello.php'; // you have no idea what's that without opening that file

use HelloWorld; // you have no idea what's that without opening that file

Take a look at the same PHP page you pointed out:

looks like wild disorder source code for people that need it encrypted.

A.smallTalk
A.bigTalk
B.smallTalk
B.bigTalk

howsoever it was mixed in the class definition one of this 4 are called.
its like Talker method xy call any of these.

Overriding members provided by traits is possible, but in my experience isn’t common. Usually you just add a trait to the class, and presto, the class has a bunch of additional functionality. If you’re overriding what a trait is doing, an interface is probably the better choice.

yes its a different spelling, i prefer obj.method instead of method(obj)

i switched Class & Super Column

Base			        Other
Beacon.ServerProfile
Beacon.ServerProfile+	Ark.ServerProfile
                        Ark.ServerProfile+		Ark.NitradoServerProfile
Beacon.ServerProfile+	SDTD.ServerProfile
                        SDTD.ServerProfile+	    SDTD.NitradoServerProfile

I’m sorry, I have no idea what you mean by this.

1 Like

I have no idea what you mean by this.

about “additional functionality for every class with the same code base”

i meant the first one have a context, its better to use at coding. (code completion)

a=b.Left(10) is the same as a=Left(b, 10)

.

I’m just not sure how that relates to this conversation.

This is the “right” way to use a trait:

<?php

trait VoidScreamer {
	public function screamIntoTheVoid(): void {
		echo 'AAAAAAAAAAA';
	}
}

class Person {
	use VoidScreamer;
}

$person = new Person();
$person->screamIntoTheVoid();

?>

Person is its own class. For the sake of argument, assume it wouldn’t make sense to make Person a subclass of VoidScreamer. If I wanted a completely independent class to have the same functionality, I just create the class and use the trait. Alternatively, I could use a singleton static method, interface, and then just fill in the method to do the same thing on each class. But why would I want to do that when this is simpler and more organized?

So… what does object-oriented calls vs procedural calls have to do with our conversation about traits?

1 Like

currently xojo can’t handle it, it looks simpler in php with 3 rows of source code.

this php example missing a function input and output to match a real use case and the class some properties.
if your methods have more than a few arguments you will gave that method an object(class) which means it is not neutral and you need an interface.

this call is mindless, it not interact with the person class.

$person->screamIntoTheVoid();

no right to exist in a class when it is just:

screamIntoTheVoid();

i admit, i not googled better traits examples

abstract view to use other methods everywhere in xojo (in compare to trait & use)

class a
 many methods

class b
 public property more as new class a

class c
 public property more as new class a

b.more.anymethod
c.more.anymethod

Yeah, there are always workarounds. But sometimes, it’s the best solution. I could keep expanding the example a bit, but the fact of the matter is real-world examples are hard to come by. Yet, I gave one in my original post. That’s usually where traits come in: when you need something like multiple inheritance in a language that does not support multiple inheritance. So what you should be looking for is examples of multiple inheritance, and figure out a way to do that in Xojo. Then it’s more obvious how traits can be helpful. In my case, I have classes that are logically two different things.

Of course, I am working on a solution but that doesn’t mean that traits don’t have a benefit.

But anyway, if you want a trait example that actually uses the Person class, here:

<?php

trait Screamer {
	public function screamMyName(): void {
		echo strtoupper($this->firstName);
	}
}

class Person {
	use VoidScreamer;
	
	protected string $firstName;
	
	public function __construct($firstName) {
		$this->firstName = $firstName;
	}
}

$person = new Person('Ted');
$person->screamMyName();

?>

No way. There’s no file here. HelloWorld trait is few lines above.

Don’t try to fight Traits, Generics, Lambdas, Asynchronous functions, etc

A language can not support them yet, but will need to embrace them at some point, or it is slowly following the path of the obsolescence.

1 Like

at least you need the context menu goto definition.
in xojo you can not add other things into same file or menu entry, everything is separated,
so i guess if trait would be integrated it is not at the same place, it would be similar like add module.

xojo could make the super input field as list input/comma separated. (that’ll never happen) :slight_smile:

your new example would not compile because of dependencies if you need VoidScreamer elsewhere
and the other class not have firstName too.

Yes, that is correct. As I opened with, traits work as if you had copied and pasted the members into the implementing class. So yes, it would be a compile error not to have a firstName property.

This does seem like a handy thing. So if I added the Screamer Trait to a “car” which is generally very different than a person, because it has doors and engine and such – I could set $car = new Car(‘Mater’); and then $car ->screamMyName(); Otherwise you would have to create some sort of parent class called “sentient thing” that both a person and a car would have to be a subclass of.
Mater

Correct. It’s basically just “add these members to this class.”

It may be add this, this and that behaviors (with enums, consts and methods) to this “structured data-container” (class or struct, if class, it may contain properties)

The compiler (or linter) may say “there’s this and that conflict” between those members of those traits (and show them). Then you can use the composition powers of the language to resolve them, as “Traits A and B have screamMyName conflict” and you say “always use Trait A->screamMyName, never B->screamMyName” or “let B->screamMyName be know as screamMyNameB” in this composition (so the conflict also disappear and you can use both methods). And you never need to touch what you designed for the original Traits, just teach new Traits to new data-containers or create a new compound Trait you can apply everywhere too.

This allows powerful designs.