Thread overview |
---|
November 22, 2014 overiding mutable methods in immutable classes | ||||
---|---|---|---|---|
| ||||
immutable class X { private int x; this(int x) { this.x = x; } ... override size_t toHash(); // error: can't override mutable method } Since toHash() cannot be overridden in an immutable class, is there a work-around? In other words, immutable X x1 = new immutable X(5); immutable X x2 = new immutable X(5); I would like for x1.toHash() to equal x2.toHash(), but this is not the case because toHash() cannot be overridden. Note also that (x1 != x2) even though they should be equal (I think...) Is this a bug or a feature? -Eric |
November 22, 2014 Re: overiding mutable methods in immutable classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Eric | On Saturday, 22 November 2014 at 00:24:39 UTC, Eric wrote: > > > > immutable class X > { > private int x; > this(int x) { this.x = x; } > ... > override size_t toHash(); // error: can't override mutable method > } > > Since toHash() cannot be overridden in an immutable class, > is there a work-around? > > In other words, > > immutable X x1 = new immutable X(5); > immutable X x2 = new immutable X(5); > > I would like for x1.toHash() to equal x2.toHash(), > but this is not the case because toHash() cannot be overridden. A class qualifier is a short-hand to qualify all members of the class. That is, all fields and methods of an `immutable class` are immutable. That's problematic here, because an immutable method cannot overload a non-immutable method, and Object.toHash is not immutable. If you need to do override a non-immutable method, don't mark the whole class as immutable. Instead, mark everything individually. And make toHash const, not immutable. class X { private immutable int x; this(int x) immutable { this.x = x; } override size_t toHash() const {...} } But think about if enforced immutability is really what you want. You don't need to mark the fields immutable to be able to construct immutable Xs. A `pure` constructor is handy, as it can construct both mutable and immutable objects. class X { private int x; this(int x) pure { this.x = x; } } void main() { auto m = new X(5); auto i = new immutable X(5); } > Note also that (x1 != x2) even though they should be equal (I think...) By default, equality of objects is defined as identity. That is, an Object is equal only to itself. Override opEquals to change that. |
November 22, 2014 Re: overiding mutable methods in immutable classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous |
> But think about if enforced immutability is really what you want.
> You don't need to mark the fields immutable to be able to
> construct immutable Xs. A `pure` constructor is handy, as it can
> construct both mutable and immutable objects.
>
> class X
> {
> private int x;
> this(int x) pure { this.x = x; }
> }
> void main()
> {
> auto m = new X(5);
> auto i = new immutable X(5);
> }
>
>> Note also that (x1 != x2) even though they should be equal (I think...)
>
> By default, equality of objects is defined as identity. That is,
> an Object is equal only to itself. Override opEquals to change
> that.
I know I can make a class immutable, but the problem is I want
to constrain a template parameter to only immutable types,
and I want to use class types.
-Eric
|
November 22, 2014 Re: overiding mutable methods in immutable classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Eric | On 11/21/14 7:24 PM, Eric wrote: > > > > immutable class X > { > private int x; > this(int x) { this.x = x; } > ... > override size_t toHash(); // error: can't override mutable method > } > > Since toHash() cannot be overridden in an immutable class, > is there a work-around? Kind of, but I don't think it's good that it works. Note that you shouldn't be able to call mutable toHash on an immutable object, but the runtime bludgeons it through: class X { override size_t toHash() {return x;} immutable: ... // everything else } This is equivalent to saying you have an immutable class, but just that one method is mutable. D lacks a mechanism to say something is mutable. > In other words, > > immutable X x1 = new immutable X(5); > immutable X x2 = new immutable X(5); > > I would like for x1.toHash() to equal x2.toHash(), > but this is not the case because toHash() cannot be overridden. > Note also that (x1 != x2) even though they should be equal (I think...) > Is this a bug or a feature? Classes are always references. This means you are comparing the class reference x1 to the class reference x2, and they point at different pieces of memory. You can override opEquals to define how to compare them, if you want != to work. I will note that opEquals *and* toHash must be overridden to work with AAs. -Steve |
November 22, 2014 Re: overiding mutable methods in immutable classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Eric | On Saturday, 22 November 2014 at 02:37:21 UTC, Eric wrote:
> I know I can make a class immutable, but the problem is I want
> to constrain a template parameter to only immutable types,
> and I want to use class types.
template Foo(T : immutable Object)
Accepts immutable(Object) and other immutable class types.
Rejects non-immutable class types like Object and const(Object),
and non-class types.
|
November 22, 2014 Re: overiding mutable methods in immutable classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | On Saturday, 22 November 2014 at 09:57:55 UTC, anonymous wrote:
> On Saturday, 22 November 2014 at 02:37:21 UTC, Eric wrote:
>> I know I can make a class immutable, but the problem is I want
>> to constrain a template parameter to only immutable types,
>> and I want to use class types.
>
> template Foo(T : immutable Object)
>
> Accepts immutable(Object) and other immutable class types.
> Rejects non-immutable class types like Object and const(Object),
> and non-class types.
Yes, but if I don't declare the class T as immutable, I don't
think this constraint will work.
-Eric
|
November 22, 2014 Re: overiding mutable methods in immutable classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Eric | On Saturday, 22 November 2014 at 15:00:00 UTC, Eric wrote:
> Yes, but if I don't declare the class T as immutable, I don't
> think this constraint will work.
You're mistaken. It works just fine.
class X /* not immutable */
{
private int x;
this(int x) pure { this.x = x; }
}
template foo(T : immutable Object)
{
void foo(T thing) {}
}
void main()
{
foo(new immutable X(5));
}
|
November 22, 2014 Re: overiding mutable methods in immutable classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous | On Saturday, 22 November 2014 at 17:06:29 UTC, anonymous wrote:
> On Saturday, 22 November 2014 at 15:00:00 UTC, Eric wrote:
>> Yes, but if I don't declare the class T as immutable, I don't
>> think this constraint will work.
>
> You're mistaken. It works just fine.
>
> class X /* not immutable */
> {
> private int x;
> this(int x) pure { this.x = x; }
> }
> template foo(T : immutable Object)
> {
> void foo(T thing) {}
> }
> void main()
> {
> foo(new immutable X(5));
> }
Yes, but this is what I really want:
class X(T : immutable Object)
{
private T x;
this(T x) pure { this.x = x; }
}
class Y
{
private int x;
this(int x) pure { this.x = x; }
}
void main()
{
immutable(Y) y = new immutable Y(5);
X!(Y) x = new X!(Y)(y);
}
// test.d(16): Error: template instance X!(Y) does not
// match template declaration X(T : immutable(Object))
|
November 22, 2014 Re: overiding mutable methods in immutable classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Eric | On Saturday, 22 November 2014 at 17:40:42 UTC, Eric wrote:
> Yes, but this is what I really want:
>
> class X(T : immutable Object)
> {
> private T x;
> this(T x) pure { this.x = x; }
> }
>
> class Y
> {
> private int x;
> this(int x) pure { this.x = x; }
> }
>
> void main()
> {
> immutable(Y) y = new immutable Y(5);
> X!(Y) x = new X!(Y)(y);
> }
>
> // test.d(16): Error: template instance X!(Y) does not
> // match template declaration X(T : immutable(Object))
I'm not sure what you're getting at. That is, I don't see which
parts of the code you want to be as they are.
For example, this works:
class X(T /* optionally, restrict T to class types:*/ /*: const
Object*/)
{
private T x;
this(T x) pure { this.x = x; }
}
/* Maybe add a convenience construction function: */
X!T newX(T)(T x) {return new X!T(x);}
class Y
{
private int x;
this(int x) pure { this.x = x; }
}
void main()
{
immutable(Y) y = new immutable Y(5);
X!(immutable Y) x = new X!(immutable Y)(y);
auto x2 = newX(y); /* same as above, but less wordy */
}
But I'm not sure if maybe I changed to much about it.
My point is, that I think it's generally a good idea to be
flexible when possible, and not make (im)mutability demands
unless actually necessary.
You may know the following, but I feel like there may be some
confusion about it: Note that immutable(Y) is a different type
from just Y. And declaring Y as `immutable class Y` wouldn't
change a thing about that, as the "immutable" there only affects
the members of Y. Objects of the bare type Y would still be
(head) mutable.
|
November 22, 2014 Re: overiding mutable methods in immutable classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to anonymous |
> But I'm not sure if maybe I changed to much about it.
>
> My point is, that I think it's generally a good idea to be
> flexible when possible, and not make (im)mutability demands
> unless actually necessary.
>
> You may know the following, but I feel like there may be some
> confusion about it: Note that immutable(Y) is a different type
> from just Y. And declaring Y as `immutable class Y` wouldn't
> change a thing about that, as the "immutable" there only affects
> the members of Y. Objects of the bare type Y would still be
> (head) mutable.
I thought I had my code working if instead of declaring
"class Y", I declared "immutable class Y", but now it is
not working for me. But finally this works:
class X(T : immutable Object)
{
private T x;
this(T x) pure { this.x = x; }
}
class Y
{
private const int x;
this(int x) pure { this.x = x; }
}
void main()
{
immutable(Y) y = new immutable Y(4);
X!(immutable(Y)) x = new X!(immutable(Y))(y);
}
Thanks for your help.
-Eric
|
Copyright © 1999-2021 by the D Language Foundation