View mode: basic / threaded / horizontal-split · Log in · Help
September 22, 2012
how is this considered hiding methods?
Can someone please tell me why the following code gives these 
errors?

Error: class main.BirdZoo use of main.VertebrateZoo.take(Animal 
animal_) hidden by BirdZoo is deprecated

Error: class main.ParrotZoo use of main.VertebrateZoo.take(Animal 
animal_) hidden by ParrotZoo is deprecated

/// The code:

	class Animal { }
	class Vertebrate { }
	class Bird: Animal { }
	class Parrot: Bird { }
	
	class VertebrateZoo
	{
		void take(Animal animal_)
		{
			if(auto vertebrate = cast(Vertebrate)animal_)
				take(vertebrate);
		}
		
		abstract void take(Vertebrate vertebrate_);
	}
	
	class BirdZoo: VertebrateZoo
	{
		override void take(Vertebrate vertebrate_)
		{
			if(auto bird = cast(Bird)vertebrate_)
				take(bird);
		}
		
		abstract void take(Bird bird_);
	}
	
	class ParrotZoo: BirdZoo
	{
		override void take(Bird bird_)
		{
			if(auto parrot = cast(Parrot)bird_)
				take(parrot);
		}
		
		abstract void take(Parrot parrot_);
	}
September 22, 2012
Re: how is this considered hiding methods?
On Saturday, 22 September 2012 at 07:48:02 UTC, Gor Gyolchanyan 
wrote:
> Can someone please tell me why the following code gives these 
> errors?
>
> Error: class main.BirdZoo use of main.VertebrateZoo.take(Animal 
> animal_) hidden by BirdZoo is deprecated
>
> Error: class main.ParrotZoo use of 
> main.VertebrateZoo.take(Animal animal_) hidden by ParrotZoo is 
> deprecated
>
> /// The code:
>
> 	class Animal { }
> 	class Vertebrate { }
> 	class Bird: Animal { }
> 	class Parrot: Bird { }
> 	
> 	class VertebrateZoo
> 	{
> 		void take(Animal animal_)
> 		{
> 			if(auto vertebrate = cast(Vertebrate)animal_)
> 				take(vertebrate);
> 		}
> 		
> 		abstract void take(Vertebrate vertebrate_);
> 	}
> 	
> 	class BirdZoo: VertebrateZoo
> 	{
> 		override void take(Vertebrate vertebrate_)
> 		{
> 			if(auto bird = cast(Bird)vertebrate_)
> 				take(bird);
> 		}
> 		
> 		abstract void take(Bird bird_);
> 	}
> 	
> 	class ParrotZoo: BirdZoo
> 	{
> 		override void take(Bird bird_)
> 		{
> 			if(auto parrot = cast(Parrot)bird_)
> 				take(parrot);
> 		}
> 		
> 		abstract void take(Parrot parrot_);
> 	}
> 	

I figured it out:

	class BirdZoo: VertebrateZoo
	{
		alias VertebrateZoo.take take;

		override void take(Vertebrate vertebrate_)
		{
			if(auto bird = cast(Bird)vertebrate_)
				take(bird);
		}
		
		abstract void take(Bird bird_);
	}
	
	class ParrotZoo: BirdZoo
	{
		alias BirdZoo.take take;

		override void take(Bird bird_)
		{
			if(auto parrot = cast(Parrot)bird_)
				take(parrot);
		}
		
		abstract void take(Parrot parrot_);
	}
September 22, 2012
Re: how is this considered hiding methods?
On Saturday, September 22, 2012 09:49:04 Gor Gyolchanyan wrote:
> Can someone please tell me why the following code gives these
> errors?
> 
> Error: class main.BirdZoo use of main.VertebrateZoo.take(Animal
> animal_) hidden by BirdZoo is deprecated
> 
> Error: class main.ParrotZoo use of main.VertebrateZoo.take(Animal
> animal_) hidden by ParrotZoo is deprecated
> 
> /// The code:
> 
> 	class Animal { }
> 	class Vertebrate { }
> 	class Bird: Animal { }
> 	class Parrot: Bird { }
> 
> 	class VertebrateZoo
> 	{
> 		void take(Animal animal_)
> 		{
> 			if(auto vertebrate = cast(Vertebrate)animal_)
> 				take(vertebrate);
> 		}
> 
> 		abstract void take(Vertebrate vertebrate_);
> 	}
> 
> 	class BirdZoo: VertebrateZoo
> 	{
> 		override void take(Vertebrate vertebrate_)
> 		{
> 			if(auto bird = cast(Bird)vertebrate_)
> 				take(bird);
> 		}
> 
> 		abstract void take(Bird bird_);
> 	}
> 
> 	class ParrotZoo: BirdZoo
> 	{
> 		override void take(Bird bird_)
> 		{
> 			if(auto parrot = cast(Parrot)bird_)
> 				take(parrot);
> 		}
> 
> 		abstract void take(Parrot parrot_);
> 	}

The problem goes away if you add

alias VertebrateZoo.take take;

It also goes away if you change take in the derived class to take Animal.

My guess is that the problem is that the version of take which takes an Animal 
is unavailable in the derived classes and is therefore "hidden." Any time that 
you add an overload to a derived class which does not exactly override a 
function in the base class, the base class overload is hidden in the derived 
class. The normal fix for this is to alias the base class version in the 
derived class. But why the compiler would now require that you do that, I 
don't know. If that's the way that thnigs currently are, it starts to become a 
bit odd that the base class functions aren't automatically available. IIRC, 
the reason that they weren't before is so that you don't get cases where 
you're not aware of what all of the overloads in a class are and end up with a 
different function being called than you expected (so it's another one of the 
function-hijacking prevention features), and I that still applies, so I guess 
that that's why still have to do it. Still, it's weird.

TDPL may explain this. I don't know. I'd have to go digging. I'm 99.99% 
certain that it explains the alias bit at least.

- Jonathan M Davis
September 22, 2012
Re: how is this considered hiding methods?
On 9/22/12, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> But why the compiler would now require that you do that, I
> don't know. If that's the way that thnigs currently are, it starts to become
> a bit odd that the base class functions aren't automatically available.

http://dlang.org/hijack.html

There's a good reason why, consider:

class Foo
{
   void foo(int) { }
}

class Bar : Foo
{
   alias super.foo foo;
   void foo(double) { }
}

void main()
{
   auto bar = new Bar;
   bar.foo(1);  // calls Foo.foo
}

Now let's say Foo is a library class and you upgrade to a new version
of the library without realizing that the base method was removed:

class Foo
{
}

class Bar : Foo
{
   alias super.foo foo;   // error
   void foo(double) { }
}

This now becomes a compile-time error. Without using the alias which
triggers the error the literal "1" would be implicitly converted to a
double and you'd end up invoking your own 'foo' method (which is no
longer an overload).
September 22, 2012
Re: how is this considered hiding methods?
On 9/22/12, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> using the alias

But I do think this can be further improved in the language. Take this
for example:

import std.stdio;

class Foo
{
   void meth(double) { writeln("Foo.meth"); }
}

class Bar : Foo
{
   alias super.meth meth;
   void meth(int) { writeln("Bar.meth"); }
}

class Doo : Bar
{
   alias super.meth meth;
   void meth(long) { writeln("Doo.meth"); }
}

void main()
{
   auto doo = new Doo;
   doo.meth(1);  // calls Bar.meth
}

Now let's say the Doo clas removes the meth overload and the alias:

class Foo
{
   void meth(double) { writeln("Foo.meth"); }
}

class Bar : Foo
{
   // gone
}

class Doo : Bar
{
   alias super.meth meth;
   void meth(long) { writeln("Doo.meth"); }
}

void main()
{
   auto doo = new Doo;
   doo.meth(1);   // now calls Doo.meth
}

We might have wanted the "super alias" in Doo to only work against the
Bar base class so the compiler can notify us if Doo.meth is removed.
The language doesn't have a way to warn us of this.

I would prefer if "super.alias" meant to take overloads of all base
classes into account and that we could use "ClassName.alias" to only
import the overload set of a specific base class. That way this would
trigger a CT error:

class Foo
{
   void meth(double) { writeln("Foo.meth"); }
}

class Bar : Foo
{
}

class Doo : Bar
{
   alias Bar.meth meth;  // error: no overload set in Bar
   void meth(long) { writeln("Doo.meth"); }
}
September 22, 2012
Re: how is this considered hiding methods?
On 9/22/12, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> Now let's say the Doo clas removes the meth overload and the alias:

Sorry that should be "the Bar class".
September 22, 2012
Re: how is this considered hiding methods?
On 9/22/12, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> I would prefer if "super.alias" meant to take overloads of all base
> classes into account.

Although this would be kind of counter-intuitive since 'super' already
means the direct base class.
Top | Discussion index | About this forum | D home