OO inheritance question - oop

Consider the following 2 methods:
class A{
void Method1(){
if(!something) return;
DoX();
DoY();
DoZ();
}
class B{
void Method2(){
if(!something) return;
DoX();
DoY();
DoP();
}
}
obviously a superclass could be written to avoid dry principle:
class Super{
virtual void Method(){
if(!something) return; //problem...
DoX();
DoY();
}
}
class A:Super{
override void Method(){
inherited Method();
DoZ();
}
}
class B:Super{
override void Method(){
inherited Method();
DoP();
}
}
The problem is the !something check where it would run out in the first example whereas in the second, it will run out of the super class's method, but do either DoZ() or DoP() in the derived class;
My question: What is the best way to solve this kind of problem? The one that comes to my hand is making the super class's method a function that returns bool
virtual bool Method(){ if(!something) return false;}
override bool Method(){ if(!inherited Method()) return;}
is this the best workaround?

How about:
class Super {
void Method() {
if (!something) return;
DoX();
DoY();
DoThingy();
}
abstract void DoThingy();
}
class A : Super {
override DoThingy() {
DoZ();
}
}
class B : Super {
override DoThingy() {
DoP();
}
}

Why not declaring another virtual method for DoP or Doz, you can wrap them if you want to keep them public with their respective names.
Like superclass :
virtual void wrapping(){};
Then each child :
void wrapping() { DoP(); }
void wrapping() { DoZ(); }
Don't know if I've been clear.

Another option: Keep the checks in the derived methods. Maybe a derived class might need a slightly different condition?
class Super{
virtual void Method(){
DoX();
DoY();
}
}
class A:Super{
override void Method(){
if(!something) return;
inherited Method();
DoZ();
}
}
class B:Super{
override void Method(){
if(!something) return;
inherited Method();
DoP();
}
}

Related

Is this considered as good approach of using interface type in class

Say i have a code as follows
interface Interface1
{
void method1();
}
interface Interface2
{
void method2();
}
class ClassWithInterfaces : Interface1,Interface2
{
void method1(){}
void method2(){}
}
Now in my "manager" class i implement this as follows :
public OtherClass
{
Interface1 interface1;
Interface2 interface2;
public void someMethod()
{
ClassWithInterfaces classWithInterfaces = new ClassWithInterfaces();
interface1 = classWithInterfaces;
interface2 = classWithInterfaces
}
}
I don't feel that this is the right way to do it hovewer i can't come up with other solutions i can't use Dependency Injection Frameworks in my project if you ask about that. Can you tell me wheter apart from DI there is a better way of doing that?
Hello and welcome to Stack Overflow :-)
You don't have to use a framework in order to do DI. In fact, there are some languages that make it impossible to use a framework for DI - e.g., C++.
Any way, in your case, the proper way to do DI is like this:
interface Interface1
{
void method1();
}
interface Interface2
{
void method2();
}
interface Interface3 : Interface1, Interface2
{
void method1();
void method2();
}
class ClassWithInterfaces : Interface3
{
void method1(){}
void method2(){}
}
public OtherClass
{
Interface3 m_interface3;
OtherClass(Interface3 interface3)
{
m_interface3 = interface3;
}
public void someMethod()
{
m_interface3.method1();
m_interface3.method2();
}
}
// And now the usage:
public main()
{
ClassWithInterfaces classWithInterfaces = new ClassWithInterfaces();
OtherClass otherClass = new OtherClass(classWithInterfaces);
}

Extends common class and implement interface

(This example written by Typescript but not only in Typescript case)
class IMyInterface {
doC:(any) => any;
}
class Common {
commonProperty:any;
doA() {
}
doB() {
}
}
class ClassA extends Common {}
class ClassB extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
class Factory {
myClass: Common;
doSomething() {
// Property 'doC' does not exist on type 'Common'
this.myClass.doC('test');
}
}
Class A and B are extended Common class, so that in Factory class can define myClass type as Common.
But Class B need to implement IMyInterface, which Common class doesn't contained. So the Factory class throws an error that the interface method is not existed on Common class.
How and what's the best way to solve this?
[Edited]
First of all, #basarat thank you very much, but I'm still curious a little,
What if there are some more classes which implements IMyInterface
class ClassC extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
class ClassD extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
class ClassE extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
In that case, I can think, I can define the doC() method in Common class.
But also I want to make ClassB, C, D and E must implement the Doc method.
please advise me,
How and what's the best way to solve this
You basically want to say that myClass is generally just Common but in a special case it might be ClassB. You can do this using a union type + using a typeguard:
class Factory {
myClass: Common | ClassB;
doSomething() {
const myClass = this.myClass;
if (myClass instanceof ClassB){
// works!
myClass.doC('test');
}
}
}
More
Complete example:
class IMyInterface {
doC:(any) => any;
}
class Common {
commonProperty:any;
doA() {
}
doB() {
}
}
class ClassA extends Common {}
class ClassB extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
class Factory {
myClass: Common | ClassB;
doSomething() {
const myClass = this.myClass;
if (myClass instanceof ClassB){
// works!
myClass.doC('test');
}
}
}
Docs
Union type : https://basarat.gitbooks.io/typescript/content/docs/types/type-system.html#union-type
Type Guard: https://basarat.gitbooks.io/typescript/content/docs/types/typeGuard.html
UPDATE
As requested, if one does want to test for the interface one needs to create a user defined type guard (docs https://basarat.gitbooks.io/typescript/content/docs/types/typeGuard.html#user-defined-type-guards). Example:
function isMyInterface(foo:any): foo is IMyInterface {
return typeof foo.doC === 'function';
}
class Factory {
myClass: Common | IMyInterface;
doSomething() {
const myClass = this.myClass;
if (isMyInterface(myClass)){
// works!
myClass.doC('test');
}
}
}
So complete code becomes :
class IMyInterface {
doC:(any) => any;
}
class Common {
commonProperty:any;
doA() {
}
doB() {
}
}
class ClassA extends Common {}
class ClassB extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
class ClassC extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
class ClassD extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
class ClassE extends Common implements IMyInterface {
doC(test:any) {
return true;
}
}
function isMyInterface(foo:any): foo is IMyInterface {
return typeof foo.doC === 'function';
}
class Factory {
myClass: Common | IMyInterface;
doSomething() {
const myClass = this.myClass;
if (isMyInterface(myClass)){
// works!
myClass.doC('test');
}
}
}

AspectJ: List<Object> pointcut args

I have this class:
public class MyClass {
public void updatePeople(List<Person> people) { //DO STUFF }
}
I want to log the size of people when updatePeople is called by AOP.
This is my aspect:
#Aspect
public class MyAspect {
#Pointcut("execution(void com.bla.bla.MyClass.updatePeople(List<Person>)) && args(people)")
public void updatePeople(List<Person> people) {}
#Before("updatePeople(people)")
public void log(List<Person> people) {
log(people.size());
}
}
But log is never called. I guess List<Person> syntax is is not correct in the pointcut. How can I do that?
Thanks.
Solved! I changed the pointcut into this:
#Pointcut("execution(void com.bla.bla.MyClass.updatePeople(..)) && args(people)")
public void updatePeople(List<Person> people) {}

Abstraction is changed?

My question is, how to redesign abstract factory.
For example, I get next abstraction of vehicles:
interface IEngine { int Power(); }
class Gasoline : IEngine { public int Power() {return 150; }}
class Diesel : IEngine { public int Power() { return 50; }}
interface IFrame { string Name(); }
class Boxed : IFrame { public string Name() { return "Boxed frame"; }}
class Hat : IFrame { public string Name() { return "Hat frame"; }}
interface TransportFactory {
IEngine CreateEngine();
IFrame CreateChassis();
}
class TrailerCar : TransportFactory {
public IEngine CreateEngine() { return new Diesel(); }
public IFrame CreateChassis() { return new Boxed(); }
}
class PrivateCar : TransportFactory {
public IEngine CreateEngine() { return new Gasoline(); }
public IFrame CreateChassis() { return new Hat(); }
}
Now, I can instantiate private or trailer car.
Some one suggest me changes: engine for trailers cars can by turbo or hybrid. Only for trailers! For private car diesel and gasoline engines still usual diesel engine.
So, if i do changes:
public enum EngineType { Hybrid, Turbo, }
interface TransportFactory
{
IEngine CreateEngine(EngineType t);
IFrame CreateChassis();
}
and i can add classes:
class GasolineHybrid : IEngine
{
public int Power()
{
return 70;
}
}
class GasolineTurbo : IEngine
{
public int Power()
{
return 170;
}
}
class DieselHybrid : IEngine
{
public int Power()
{
return 60;
}
}
class DieselTurbo : IEngine
{
public int Power()
{
return 98;
}
}
it is good, but (!!!) private car nothing to do with it!!!
What kind of design can i use? Old abstraction get incorrect?
Thanks a lot!!!
How about:
class GasolineHybridTrailerCar : TransportFactory
{
public IEngine CreateEngine()
{
return new GasolineHybrid();
}
...
}
class GasolineTurboTrailerCar : TransportFactory
{
public IEngine CreateEngine()
{
return new GasolineTurbo();
}
...
}
class DieselHybridTrailerCar : TransportFactory
{
public IEngine CreateEngine()
{
return new DieselHybrid();
}
...
}
class DieselTurboTrailerCar : TransportFactory
{
public IEngine CreateEngine()
{
return new DieselTurbo();
}
...
}
The idea behind spawning numerous classes is to remove client's ability to do wrong choice. Since you said hybrid and turbo engines do not make sense for private cars, then keeping
IEngine CreateEngine(EngineType t);
will require from private car factory additional efforts to refuse incorrect arguments.
I am not sure did you mean it, but class names suggest that cars are products of factory. In classic relation it will be factory --produce--> product. It is kinky and fun how you put it via generalization, but could be hardly recognizable by others. The beauty of patterns is that once you hear its one word name, then you feel confident about all the internals the implementation could imply.
There is pattern Builder. Would it be more suitable name for your design?
Remember that parameters need not be part of the interface, they can be passed to the constructor of the implementation. So you can still keep your old interface:
interface TransportFactory
{
IEngine CreateEngine();
IFrame CreateChassis();
}
but pass the EngineTypeto the TrailerCar constructor:
class TrailerCar : TransportFactory {
private readonly EngineType engineType;
public TrailerCar(EngineType engineType)
{
this.engineType = engineType;
}
public IEngine CreateEngine()
{
if (engineType == EngineType.Hybrid) return new DieselHybrid();
else return new DieselTurbo();
}
public IFrame CreateChassis() { return new Boxed(); }
}

Overriding FluentNHibernate DefaultCascade for many types at once

I have an abstract entity base class defined like this:
public abstract class SessionItem : Entity
{
public virtual Session Session { get; set; }
}
In addition, I'm using auto mapping:
private AutoPersistenceModel CreateAutomappings()
{
return AutoMap
// configuration
.Conventions.Add(DefaultCascade.All())
// more configuration
}
SessionItem has several derived classes/tables, and I'd like to override the cascading policy for all of them. I tried the following:
public class SessionItemAutommapingOverride : IAutoMappingOverride<SessionItem>
{
public void Override(AutoMapping<SessionItem> mapping)
{
mapping.References(x => x.Session).Cascade.None();
}
}
But unfortunately the override is not called since SessionItem is abstract (and is not mapped). I prefer to avoid overriding it for each subclass (using IAutoMappingOverride).
Is there any way to override cascading for multiple types, without using IAutoMappingOverride<> for each one?
public class SessionReferenceCascadeNone : IReferenceConvention, IReferenceConventionAcceptance
{
public void Accept(IAcceptanceCriteria<IManyToOneInspector> criteria)
{
criteria.Expect(x =>
typeof(SessionItem).IsAssignableFrom(x.EntityType) &&
x.Property.PropertyType == typeof(Session));
}
public void Apply(IManyToOneInstance instance)
{
instance.Cascade.None();
}
}
Apparently this is possible by using IReferenceConvention:
public class CascadeNoneOverrideConvention : IReferenceConvention
{
public void Apply(IManyToOneInstance instance)
{
// override
}
}