![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Fredrik Eriksson <fe79}--at--{yahoo}--dot--{com> wrote:
> On Wed, 21 Jan 2009 21:17:56 +0100, Darren New <dne### [at] san rr com> wrote:
> >
> > You always could do it in Smalltalk, just like you do in Ruby. One
> > advantage C# has is that you're not *actually* changing the string
> > class; it's just syntactic sugar. It's more like a C++ friend, except
> > with method/object syntax.
> It is nothing like 'friend' in C++. As I understand it, extensions only
> have access to the public interface of the extended class. Semantically,
> they seem much more like ordinary free functions in C++.
Unless I'm missing something, I really fail to see how this is a
useful feature.
Basically, it seems, that instead of having to write, for example,
"someFunction(anObject)" you can write "anObject.someFunction()".
In other words, you simply can write the same thing with a slightly
different syntax, but otherwise there's no difference. I really fail
to see the usefulness of this.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> Fredrik Eriksson <fe79}--at--{yahoo}--dot--{com> wrote:
>> On Wed, 21 Jan 2009 21:17:56 +0100, Darren New <dne### [at] san rr com> wrote:
>>> You always could do it in Smalltalk, just like you do in Ruby. One
>>> advantage C# has is that you're not *actually* changing the string
>>> class; it's just syntactic sugar. It's more like a C++ friend, except
>>> with method/object syntax.
>
>> It is nothing like 'friend' in C++. As I understand it, extensions only
>> have access to the public interface of the extended class. Semantically,
>> they seem much more like ordinary free functions in C++.
>
> Unless I'm missing something, I really fail to see how this is a
> useful feature.
>
> Basically, it seems, that instead of having to write, for example,
> "someFunction(anObject)" you can write "anObject.someFunction()".
>
> In other words, you simply can write the same thing with a slightly
> different syntax, but otherwise there's no difference. I really fail
> to see the usefulness of this.
>
Its syntatic sugar. A convenience.
--
~Mike
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> Basically, it seems, that instead of having to write, for example,
> "someFunction(anObject)" you can write "anObject.someFunction()".
Syntax sugar. And let lets you do things like
"Hello".toUpper().myConversion().trim("o")
so you can chain them together.
The same benefit you get in C++ from being able to make classes with no
virtual members. You often talk about how you can have an array of points
in C++ without any extra overhead and still treat them like objects, yes?
Same sort of thing here.
Note too that it might interact with overloading and implicit casts.
short s = ...;
s.myThing(); // I know what this calls.
yourThing(s); // Does this cast "s" to an integer first?
--
Darren New, San Diego CA, USA (PST)
"Ouch ouch ouch!"
"What's wrong? Noodles too hot?"
"No, I have Chopstick Tunnel Syndrome."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> Warp wrote:
> > Basically, it seems, that instead of having to write, for example,
> > "someFunction(anObject)" you can write "anObject.someFunction()".
> Syntax sugar. And let lets you do things like
> "Hello".toUpper().myConversion().trim("o")
> so you can chain them together.
> The same benefit you get in C++ from being able to make classes with no
> virtual members. You often talk about how you can have an array of points
> in C++ without any extra overhead and still treat them like objects, yes?
> Same sort of thing here.
I'm not sure it's the same thing.
The idea with having objects rather than raw data is that objects can
be made abstract, ie. have an abstract public interface which hides the
implementation).
I don't see how "anObject.someFunction()" hides the implementation
better than "someFunction(anObject)", especially given that the former
does not add any access rights for the function in question (like
declaring a function as friend would).
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> The idea with having objects rather than raw data is that objects can
> be made abstract, ie. have an abstract public interface which hides the
> implementation).
So why is it better to have member functions at all, vs just passing the
object to a function? What's the benefit of being able to say
p = pixels[23].lightened();
vs
p = lightened(pixels[23]); // Like you would in Java
> I don't see how "anObject.someFunction()" hides the implementation
> better than "someFunction(anObject)",
Because it looks like it's part of the class. You don't have to remember
which members are built in and which ones were added by a library you're using.
For example, there's LINQ (which is sort of
relational-queries-on-all-data-types), which adds all sorts of query
semantics to built-in enumerations and such. So you can do something like
var people = new array[] {
new Person("Fred", ...),
new Person("Steve", ...),
....
};
var query = people.Where(p=>p.Name.startsWith("S"))
.Select(p=>p.Name.toUpper());
That gives you back an enumeration over the uppercased names of the people
in the array whose name starts with "S". The "Where" and "Select" names were
added by LINQ.
But yeah, it's syntactic sugar. It lets you add methods to classes (and
their subclasses) that are already in existence without modifying the
already-compiled classes. It's syntactic sugar, in the same way that any
distinguished-caller syntax in a method-oriented OO language is syntactic sugar.
--
Darren New, San Diego CA, USA (PST)
"Ouch ouch ouch!"
"What's wrong? Noodles too hot?"
"No, I have Chopstick Tunnel Syndrome."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New wrote:
> Fredrik Eriksson wrote:
>> On Wed, 21 Jan 2009 21:17:56 +0100, Darren New <dne### [at] san rr com> wrote:
>>>
>>> You always could do it in Smalltalk, just like you do in Ruby. One
>>> advantage C# has is that you're not *actually* changing the string
>>> class; it's just syntactic sugar. It's more like a C++ friend, except
>>> with method/object syntax.
>>
>> It is nothing like 'friend' in C++.
>
> Well, yes, there are a lot of differences. I suppose in thinking more
> it's not really like "friend" at all, no. :-)
Thinking more, it's exactly the *opposite* of friend.
A friend function lets you take something with function-call syntax and give
it access to the private bits of a class as if it were a member.
This thing in C# lets you take something with function-call semantics and
make it look like a member function without giving it access to the private
parts of the class.
But it *is* something that I've missed in lots of OO languages - the ability
to "fix" the built-in classes or classes in libraries without having to
subclass them and deal with getting the right classes instantiated.
--
Darren New, San Diego CA, USA (PST)
"Ouch ouch ouch!"
"What's wrong? Noodles too hot?"
"No, I have Chopstick Tunnel Syndrome."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> In other words, you simply can write the same thing with a slightly
> different syntax, but otherwise there's no difference. I really fail
> to see the usefulness of this.
It *is* syntax sugar.
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> Warp wrote:
> > The idea with having objects rather than raw data is that objects can
> > be made abstract, ie. have an abstract public interface which hides the
> > implementation).
> So why is it better to have member functions at all, vs just passing the
> object to a function? What's the benefit of being able to say
> p = pixels[23].lightened();
> vs
> p = lightened(pixels[23]); // Like you would in Java
The benefit is that, at least in theory, the member function can be
dynamically bound, while the regular function can't.
With static member functions I suppose it doesn't make too much of a
difference (except that they are less writing because you don't have to
befriend all the functions explicitly).
Although in some situations it could make a difference also with static
member functions, regarding to access rights. For example, a member
function of a derived class can access the functions in the protected
part of the base class, but an regular function can't. (Making the regular
function a friend of the base class would open even the private part of
it, which might not be what you want.)
> > I don't see how "anObject.someFunction()" hides the implementation
> > better than "someFunction(anObject)",
> Because it looks like it's part of the class. You don't have to remember
> which members are built in and which ones were added by a library you're using.
One could maybe argue that that's a *bad* thing. If it looks like part
of the class but isn't, that might cause problems when you reuse the class
somewhere else, where you might not have the extension in question.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> The benefit is that, at least in theory, the member function can be
> dynamically bound, while the regular function can't.
But not on an object that only occupies four bytes, which is your usual
example. :-)
> Although in some situations it could make a difference also with static
> member functions, regarding to access rights. For example, a member
> function of a derived class can access the functions in the protected
> part of the base class, but an regular function can't. (Making the regular
> function a friend of the base class would open even the private part of
> it, which might not be what you want.)
C# also has an assembly-level rights declaration. So instead of friends, you
declare the things you want befriended "internal". So for example, the link
pointers in a linked list cell can be tagged "internal", which basically
means any other classes in the same DLL can access them[1].
>> Because it looks like it's part of the class. You don't have to remember
>> which members are built in and which ones were added by a library you're using.
>
> One could maybe argue that that's a *bad* thing. If it looks like part
> of the class but isn't, that might cause problems when you reuse the class
> somewhere else, where you might not have the extension in question.
It isn't defined as part of the class. That's kind of the point. It's
declared[2] only where you import it. Hence, you can make such an extention
for your code, and I can make one for my code, and it doesn't conflict
unless I want to use both, at which point I fall back to the
fully-namespace-qualified form of the call. Unless I import the module
defining the function, the function isn't visible as a pseudo-member.
Incidentally, you can also declare something as a "partial member function"
in a class, which gives it a declaration but not a definition. If you never
define it, calls to it act like they are just empty functions (i.e., they
have no effect). If you do define it, then the function gets called. (I
haven't really followed this up much, but I'm guessing it has to be a void
function, and I'm not sure how this is helpful in the given environment, but
it's not the sort of thing you put in without a use case in mind. :-)
This is distinct from a "partial class", where the code (and declarations)
for one class are split across multiple source files.
[1] Lies-to-children. It's a bit more complicated than that, but that's the
basics of it.
[2] ...to use the terminology of C here distinguishing declare/define.
--
Darren New, San Diego CA, USA (PST)
"Ouch ouch ouch!"
"What's wrong? Noodles too hot?"
"No, I have Chopstick Tunnel Syndrome."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> Darren New <dne### [at] san rr com> wrote:
>> Warp wrote:
>>> The idea with having objects rather than raw data is that objects can
>>> be made abstract, ie. have an abstract public interface which hides the
>>> implementation).
>
>> So why is it better to have member functions at all, vs just passing the
>> object to a function? What's the benefit of being able to say
>> p = pixels[23].lightened();
>> vs
>> p = lightened(pixels[23]); // Like you would in Java
>
> The benefit is that, at least in theory, the member function can be
> dynamically bound, while the regular function can't.
BTW, it *can* be dynamically bound in languages where this is supported. Ada
leaps to mind. There's no distinguished-caller syntax in Ada - all the OO
features are done by what *looks* like overloading but actually turns out to
be dynamic binding if you've said to do so.
But yeah, it's syntax sugar, like overloading operators is.
--
Darren New, San Diego CA, USA (PST)
"Ouch ouch ouch!"
"What's wrong? Noodles too hot?"
"No, I have Chopstick Tunnel Syndrome."
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |