I have two classes A and B in which two properties 'prop1' and 'prop2' are common. How can I have compostion implemented. May be Class C can have these common properties. Its a has-a relationship and not is-a.
public class A {
public int Prop1{get;set;}
public int Prop2 {get; set;}
public int Prop3{get;set;}
public int Prop4 {get; set;}
}
public class B {
public int Prop1{get;set;}
public int Prop2 {get; set;}
public int Prop5{get;set;}
public int Prop6 {get; set;}
}
If I have a interface say C and have these two common properties in it would that classify as composition? Something like
inferace C {
int Prop1{get;set;}
int Prop2 {get; set;}
}
public class A : C
{
}
public class B : C
{
}
Thanks in advance.
Implementing an interface is not composition, although that would be an alternative way to avoid duplicating code.
To do this using composition, you should create a new class with Prop1 and Prop2, and have an instance of this class as a property of ClassA and ClassB.
public class CompositeKey
{
public int Prop1 { get; set; }
public int Prop2 { get; set; }
}
public class A
{
public CompositeKey Key { get; set; }
public int Prop3 { get; set; }
public int Prop4 { get; set; }
}
...
This is a bit more flexible than using an interface because you can assign any subtype of CompositeKey to your property at run time, but the main reason you should do it this way is because class A has a composite key, you don't want to use your class as a CompositeKey.
Related
I have an inheritance tree, which looks like this:
Foo and Bar both have an Id, as defined through an specific Id class.
The id classes itself are derived from a common base class.
I would now like to write an interface which can encompass both Foo and Bar,
but the compiler does not allow that, I would have to use BaseId as the type in Foo and Bar, but I would like to avoid that.
public class BaseId
{
public string Id {get; set;}
}
public class FooId: BaseId
{}
public class BarId: BaseId
{}
public interface MyInterface
{
public BaseId Id {get; set; }
}
public class Foo: MyInterface
{
public FooId Id {get; set;}
}
public class Bar: MyInterface
{
public BarId Id {get; set;}
}
Generics can help here. First you define interface like this:
public interface IMyInterface<out T> where T : BaseId {
T Id { get; }
}
And then you can implement it like this:
public class Foo : IMyInterface<FooId> {
public FooId Id { get; set; }
}
public class Bar : IMyInterface<BarId> {
public BarId Id { get; set; }
}
Achieving your goal to use BarId and FooId in specific classes.
Both classes are also castable to IMyInterface<BaseId> in case you are in situation where you don't know the exact id type:
Foo foo = new Foo();
// works fine
var asId = (IMyInterface<BaseId>)foo;
I'm unsure how to go about implementing this particular idea of I have a class lets call it EnhancedUserInput that will have some variables that all of the input types will have and a particular subclass depending on the need during operation so some extra variables and a list so for example sub classes of it would be MultipleChoice which would have MinSelection, MaxSelection and a list of a type called option with their own variables ect and then another possible sub class called ExplicitAgreement which would have the variables inputLabel1, inputLabel2 and a list of type BinaryInput which would have their own variables.
So far from what I understand the best way going about this would be to have some type of generic variable? I'll show some code to try and help get what it is I need across but was just wondering is there an easy way of doing this that I am unaware of?
public class EnhancedCustomerInput
{
public string Title { get; set;}
public bool ResponseOptional { get; set;}
public string CancelLabel { get; set;}
public string SubmitLabel { get; set}
// this is where I am unsure of how to go about it
public object inputType
{
MultipleChoice
ExplicitAgreement
}
}
public class MultipleChoice
{
public List<MultipleChoiceOption> Options { get; set; }
public int MinSelected { get; set; }
public int MaxSelected { get; set; }
}
public class ExplicitAgreement
{
public List<BinaryInputOption> Buttons { get; set; }
public string InputLabel1 { get; set; }
public string InputLabel2 { get; set; }
}
what would be the best path for this solution I can think of some possible ways but they would be a bit figity and was wondering if there are any simple ways?
Seems to me that you may have this the wrong way around. Maybe what you want is to just use class inheritance?
public class EnhancedCustomerInput
{
public string Title { get; set;}
public bool ResponseOptional { get; set;}
public string CancelLabel { get; set;}
public string SubmitLabel { get; set}
}
public class MultipleChoice : EnhancedCustomerInput
{
public List<MultipleChoiceOption> Options { get; set; }
public int MinSelected { get; set; }
public int MaxSelected { get; set; }
}
public class ExplicitAgreement : EnhancedCustomerInput
{
public List<BinaryInputOption> Buttons { get; set; }
public string InputLabel1 { get; set; }
public string InputLabel2 { get; set; }
}
Steve Harris's inheritance suggestion is good. Your original option to use Composition can work just fine, too:
public class EnhancedCustomerInput
{
public string Title { get; set;}
public bool ResponseOptional { get; set;}
public string CancelLabel { get; set;}
public string SubmitLabel { get; set; }
public object InputData { get; set; }
}
The only problem is that consumers of your code need to know that InputData can be one of several different types, and you presumably need logic to switch on their type. You can add comments to the property to give people a hint, or you can use a library like LanguageExt, which provides an Either type:
public class EnhancedCustomerInput
{
public string Title { get; set;}
public bool ResponseOptional { get; set;}
public string CancelLabel { get; set;}
public string SubmitLabel { get; set; }
public Either<MultipleChoice, ExplicitAgreement> InputData { get; set; }
}
This makes it much more obvious which types InputData can be, but would get very unwieldy if you have more than two possibilities.
You could also declare an interface that InputData must implement, which would make it easier for developers to find all the types that are intended to be used there. But an empty interface is considered to be a code smell because it indicates you're using interfaces for something they weren't really intended for.
Another option I've found to work well is to define an enum type to help identify which different types of input data you can have:
public class EnhancedCustomerInput
{
public string Title { get; set;}
public bool ResponseOptional { get; set;}
public string CancelLabel { get; set;}
public string SubmitLabel { get; set; }
public InputType InputType { get; set; }
public object InputData { get; set; }
}
public enum InputType { MultipleChoice, ExplicitAgreement }
This gives your business logic a specific set of possible types that you can switch your logic on, and works particularly well when the class is going to be serialized and deserialized, because then you can tell the deserializer which specific type of object to deserialize InputData to.
There are lots of options, each with their advantages and disadvantages.
I have a class of several fields:
class Entity{
public int field1 {get; set;}
public int field2 {get; set;}
public int field3 {get; set;}
}
However, I want to be able to reuse this class with the other types: string or bool maybe.
But the compiler does not like if I replace public int field1 {get; set;} with public T field1 {get; set;}
What is the best way to achieve this goal?
You'll need a generic parameter on your type, like this:
class Entity<T> {
public T field1 {get; set;}
public T field2 {get; set;}
public T field3 {get; set;}
}
You can then re-use this like so:
class EntityOfInt : Entity<int> {
///field1 is an int
///field2 is an int
///field3 is an int
}
In .NET 4 and above you can use dynamic
class Entity {
public dynamic field1 {get; set;}
public dynamic field2 {get; set;}
public dynamic field3 {get; set;}
}
possible overide
class Foo : Entity {
public new string field1 {get; set;}
public new int field2 {get; set;}
//field3 is still dynamic
}
This way you can still do boxing and unboxing for both types, and have your fields exposed. If not overrwriten, they will stay dynamic. So you can have simple class syntax and possibility for multiple unconstrained templates within one class.
class above using generic template
class Entity<T1,T2,T3>
where T3: new()
{
public T1 field1 {get; set;}
public T2 field2 {get; set;}
public T3 field3 {get; set;}
}
as you can see this can quickly get out of hand,
but remember, this is not type safe as method with class Entity<T>, because dynamic fields will accept all types, and override previously used. And you will have to unbox it every time you want to use it as object.
For more information see MSDN
MSDN
You can use multiple generic types:
public class Entity<T1, T2, T3, T4>
{
public virtual T1 Field1 {get;set;}
public T2 Field2 { get; set; }
public T3 Field3 { get; set; }
public T4 Field4 { get; set; }
}
public class Derived : Entity<int, string, bool, int>
{
public override int Field1 { get; set; }
}
I have a class with 2 interfaces, and I have some superclasses with subclasses, I would like the superclasses to inherit both interfaces. if I just reference the class the interfaces its in, will it work? ie SuperClass : Myinterfaces
here is the class with the interfaces
public class Myinterfaces
{
public interface IBakeable
{
int OvenTemp { get; }
}
public interface IAccounting
{
int Cost { get; }
}
public enum Colors
{
red = 1,
blue,
yellow
}
}
and heres an example of the superclass
public class CeramicsSuperClass : Myinterfaces
{
public string ItemName { get; set; }
public int Cost { get; set; }
public int OvenTemp { get; set; }
}
public class Vases : CeramicsSuperClass
{
private int _BaseDiam;
public Vases(int diam)
{
_BaseDiam = diam;
}
}
You are doing in a wrong way to implement multi-interfaces for a class, try this instead:
public class CeramicsSuperClass : IBakeable, IAccounting {
public string ItemName { get; set; }
public int Cost { get; set; }
public int OvenTemp { get; set; }
}
A class can inherit from only another class but it can implement as many interfaces as possible. When a class inherits from another class and implement some interface, the base class should be listed first, then the interfaces go after like this:
//class A inherits from class B and implements 2 interfaces IC and ID
public class A : B, IC, ID {
//...
}
Simple answer:
You can inherit mulitple interfaces, not multiple classes.
public interface InterfaceA
{
string PropertyA {get;}
}
public interface InterfaceB
{
string PropertyB {get;}
}
public abstract class BaseClassForOthers : InterfaceA, InterfaceB
{
private string PropertyA {get; private set;}
private string PropertyA {get; private set;}
public BaseClassForOthers (string a, string b)
{
PropertyA = a;
PropertyB = b;
}
}
public class SubClass : BaseClassForOthers
{
public SubClass (string a, string b)
: base(a, b)
{
}
}
may be looking here will get you in the general direction (msdn link about interface usage):
http://msdn.microsoft.com/en-us/library/vstudio/ms173156.aspx
I have three classes A,B and C,
some properties are in all three classes, some not
public class A
{
public string Firstname {get; set;}
public string Lastname {get; set;}
public int ID {get; set;}
public int xxx {get; set} // only in class A
public int yyy{get; set} // only in class A
...
}
public class B
{
public string Firstname {get; set;}
public string Lastname {get; set;}
public int ID {get; set;}
public int aaa {get; set} // only in class B
public int bbb {get; set} // only in class B
...
}
public class C
{
public string Firstname {get; set;}
public string Lastname {get; set;}
public int ID {get; set;}
public int kkk {get; set} // only in class C
public int ppp {get; set} // only in class C
...
}
I want to call the Execute method of class XYZ ...
public class XYZ
{
public override Execute<T>() where T: Generic_T, new()
{
T abc = new T();
...
Debug.WriteLine(abc.Firstname + ”, “ + abc.Lastname + “, “ + abc.ID);
}
}
... with all three classes,like:
XYZ x1 = new XYZ();
XYZ.Execute<A>();
XYZ x2 = new XYZ();
XYZ.Execute<B>();
XYZ x3 = new XYZ();
XYZ.Execute<C>();
My idea doesn’t work:
public class Generic_T
{
public static implicit operator A(Generic_T x)
{
return (A)x.MemberwiseClone();
}
}
Where is the mistake?
Thanks in advance!
Mistakes:
What is CloneMemberwise() ?
If you meant MemberwiseClone(), you can't call it there. It is a protected member.
You cannot call properties on a type. Here: T.Firstname, T.Lastname, etc.
It is Debug, not Degub.
You do not pass a value/reference in to the Execute method.
Neither A, B or C derives from Generic_T, so the constraint on the Execute method will fail.
Class names do not end with (). You had class A() which I re-edited already.
A or any class cannot be automagically converted to Generic_T.
You should be using inheritance, I suspect Generic_T should be a base class.
You do not have a specific question
Possible suggestion:
public abstract class Generic_T
{
public string Firstname {get; set;}
public string Lastname {get; set;}
public int ID {get; set;}
}
public class A : Generic_T
{
public int xxx {get; set} // only in class A
public int yyy{get; set} // only in class A
...
}
public class B : Generic_T
{
public int aaa {get; set} // only in class B
public int bbb {get; set} // only in class B
...
}
public class C : Generic_T
{
public int kkk {get; set} // only in class C
public int ppp {get; set} // only in class C
...
}
Also there is not reason to convert any of the derived classes to Generic_T as they as an instance of Generic_T already.
All of this information is normally explained in most introductory texts for C#/.NET. Failure to understand them, will make your life miserable.
Don't know why do you need Generic_T in your code.
To force Execute work you need to implement following interface
interface IFoo
{
int ID {get; set;}
string LastName {get; set;}
string FirstName {get; set;}
}
Then your execute method will look like this:
public override Execute<T>(T obj) where T: new(), IFoo
{
Debug.WriteLine(obj.Firstname + ”, “ + obj.Lastname + “, “ + obj.ID);
}