Skip to content

Instantly share code, notes, and snippets.

@mphuff
Last active February 1, 2017 16:42
Show Gist options
  • Save mphuff/05a410e6d619eb81f227facd001b38ca to your computer and use it in GitHub Desktop.
Save mphuff/05a410e6d619eb81f227facd001b38ca to your computer and use it in GitHub Desktop.
namespace AnimalKingdom
{
// I'm sticking a bit more with pseudo-code than FORMAL c-sharp (I'm a bit rusty there)
// More worth understanding some of the key concepts I would look for as an interviewer here:
// 1) Inheritance - check - you've got the idea of this in the bag
// 2) Encapsulation - you don't necessarily want just anybody to be able to take your object and modify properties about it
// - By setting the setters to private, utilizing them in a constructor (or other private-to-Animal method), you encapsulate any logic
// that may accompany that. Imagine having some logic in Animal base where, given a size and weight, you perform validation on that
// pair of data. If just anybody is able to modify the members, you wouldn't necessarily force validation. Yes, C# makes it a bit
// simpler with their get/set built-ins but it's best practice overall not to depend on the public get; set; methodology given that
// it doesn't translate to 'best oop' practice of encapsulation very well.
// 3) Abstraction -
// 4) Polymorphism - check - achieved at runtime through your use of inheritance
// TIP: Don't try to get too formal with 'generics' - it would definitely get in the way at an interview. Generics
// are a fantastic tool (e.g. <T>...) but not in simple OOP exercises. I've stripped them out of here for the purposes
// of simplicity in what I'm trying to convey with respect to the question at large.
// Keeping it at Animal is good enough - the vast majority of programming languages don't support generics.
public abstract class Animal
{
// I would argue you should have a base constructor instead of a Produce method which doesn't
// explicitly state what is effectively required to make a new Animal:
protected Animal(double size, double weight) {
this.AnimalSize = size;
this.AnimalWeight = weight;
}
//'double' type here used for simplicity would rather use convertable unit types
public double AnimalSize {get; private set;} //eg cubic inches
public double AnimalWeight{get; private set;} //eg pounds
}
// Making both Animal and EggLayer abstract prevents somebody from actually instantiating them.
// However, you code can pass them around as if they are a thing (Polymorphism) that can be operated on.
// They're not super interesting objects but nonetheless serve the purpose at hand.
public abstract class EggLayer:Animal, ILaysEggs
{
protected EggLayer(double size, double weight) : base(size, weight) {
// Other constructor logic for EggLayer?
}
public Egg LayEgg()
{
return new Egg();
}
}
// Similar to above, Bird now is probably an OK class to actually instantiate a new one of (if you don't know the type).
// Changing everything to Public here will allow you to do so obviously. But now you can cast Bird to an EggLayer OR
// an Animal as your needs require.
public class Bird: EggLayer, ICanFly
{
public Bird(double wingSpan, double size, double weight) : base(size, weight) {
this.WingSpan = wingSpan;
}
public Fly()
{
//Go places
}
public abstract double WingSpan {get; private set;}
}
public class Sparrow: Bird<Sparrow>, ICarnivore, IHerbavore
{
//unique sparrow functionality
public Sparrow()
{
AnimalSize =
Prey[] = new Animal[]{Worm}; //Worm is a simple animal type can be defined if needed
WingSpan = 1;
}
public bool TryHunt()
{
//Do a hunt function using Prey property probably within an Area/Habitat type object
}
public bool TryScavenge()
{
//Look for seeds etc,
}
//Add 'TryConsume' for
public void Consume(Animal prey)
{
//Could extract this function...
bool isValid = false;
for(i=0,i < Prey[].Count, i++)
{
if(Prey[i] == prey)
{
isValid = true;
break;
}
}
if(!isValid)
throw;
//Do Removal of 'prey' etc
}
}
public class Egg<T>: Animal<Egg<T>> //T extends Animal I don't know the notation in C#? looks like it's 'where T: Animal'
{
public Egg()
{
Child = new T();
}
private T Child{get;set;}
public Animal Produce()
{
return Hatch();
}
private T Hatch()
{
return Child;
}
}
//Interfaces
public interface ICarnivore //Predator
{
Animal[] Prey{get;set;}
bool TryHunt();
void Consume(Animal prey);
}
public interface IHerbavore
{
//Try to find/eat something that isn't an animal
bool TryScavenge();
}
public interface ICanFly
{
//Again Double used for simplicity
double WingSpan{get;set;}
void Fly();
}
public interface ILaysEggs
{
Egg LayEgg();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment