www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - how is this considered hiding methods?

reply "Gor Gyolchanyan" <gor.f.gyolchanyan gmail.com> writes:
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_);
	}
	
Sep 22 2012
next sibling parent "Gor Gyolchanyan" <gor.f.gyolchanyan gmail.com> writes:
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_); }
Sep 22 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Sep 22 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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).
Sep 22 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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"); } }
Sep 22 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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".
Sep 22 2012
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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.
Sep 22 2012