Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# OOP Composition and Generalization at the same time

This might be a simple/basic OOP question, but I still cannot figure out how to solve it. I had the following problem during an interview : make an UML class diagram and write the basic code for a "smart"phone which contains the functionalities of a telephone and of an mp3 player. We've got with the following (accepted) solution :

class Telephone 
{
    public string name { get; set; }

    public Telephone()
    {
        name = "name telephone";
    }
}

class MP3 
{
    public string name { get; set; }

    public MP3()
    {
        name = "name mp3";
    }
}

And the "smart"phone class :

class TelephoneMP3 
{
    public Telephone tel;
    public MP3 mp3;

    public TelephoneMP3()
    {
        tel = new Telephone();
        mp3 = new MP3();
    }
}

As you can see, we have a composition relation between the TelephoneMP3 and the Telephone/MP3 classes.

But, using this code, the TelephoneMP3 is not a Telephone and the TelephoneMP3 is not an MP3 either, which is not logical. So, what changes should I make in order to make this valid ? For example, this kind of test :

if (telMp3 is Telephone)
{
    Console.WriteLine("TelephoneMP3 is telephone");
}           
if (telMp3 is MP3)
{
    Console.WriteLine("TelephoneMP3 is mp3");
}

The modifications could be made using the following remarks :

  1. Telephone / MP3 / TelephoneMP3 must remain classes (all 3 of them)
  2. I could add interfaces / other classes if necessary
  3. TelephoneMP3 must not duplicate all the functionalities from a Telephone / MP3 (for example during an inheritance from an interface where the TelephoneMP3 will be obliged to write the code from all the interface's members)

Thank you in advance

like image 778
IonR Avatar asked Jun 30 '14 07:06

IonR


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

Is C language easy?

Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.

What is C in C language?

What is C? C is a general-purpose programming language created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.

What is the full name of C?

In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.


2 Answers

Since C# doesn't support multiple inheritance, consider using interfaces instead:

public interface Phone{ ... }
public interface Mp3{ ... }

public class Telephone : Phone{ ... }
public class Mp3Player : Mp3{ ... }
public class Smartphone : Phone, Mp3{ ... }

This way Smartphone is both Phone and Mp3. If you are in need to write a method which operates on a Telephone, use the Phone interface instead. This way you'll be able to pass either Telephone or Smartphone as an argument.

like image 74
Bartek Maraszek Avatar answered Nov 04 '22 12:11

Bartek Maraszek


There are some good answers here. The answers which say to use interfaces are good, and that's what the interviewer is likely looking for. However, I would consider simply denying the premise that the "is-a-kind-of" relationship being satisified is a good idea. Rather, I would consider using a service provider organization:

public interface ITelephone { ... }
internal class MyTelephone : ITelephone { ... }
public interface IMusicPlayer { ... }
internal class MyPlayer : IMusicPlayer { ... }
public interface IServiceProvider
{
  T QueryService<T>() where T : class;
}

internal class MyDevice : IServiceProvider
{
  MyTelephone phone = new MyTelephone();
  MyPlayer player = new MyPlayer();
  public T QueryService<T>() where T : class
  {
      if (typeof(T) == typeof(ITelephone)) return (T)(object)phone;
      if (typeof(T) == typeof(IPlayer)) return (T)(object)player;
      return null;
  }
}

Now a caller has a MyDevice in hand via its IServiceProvider interface. You ask it

ITelephone phone = myDevice.QueryService<ITelephone>();

and if phone is non-null, then the device can act like a phone. But

myDevice is ITelephone

is false. The device is not a phone, it knows how to find you something that acts like a phone.

For more in this vein, study plug-in architectures such as MAF.

like image 18
Eric Lippert Avatar answered Nov 04 '22 12:11

Eric Lippert