Class-Simple-Readonly-Cached

 view release on metacpan or  search on metacpan

lib/Class/Simple/Readonly/Cached.pm  view on Meta::CPAN

=head3 API SPECIFICATION

    # Input  None
    # Output { type => 'hashref',
    #          keys => { hits   => 'hashref|undef',
    #                    misses => 'hashref|undef' } }

=head3 MESSAGES

    (none)

=cut

sub state
{
	my $self = shift;
	return { hits => $self->{_hits}, misses => $self->{_misses} };
}

=head2 can

Report whether the inner object (or this class) can respond to a
given method.  Overrides C<UNIVERSAL::can> to account for the
decorator pattern.

=head3 Returns

A code reference if the method exists, C<undef> otherwise.

=head3 EXAMPLE

    my $code = $cached->can('compute');
    $code->($cached) if $code;

=head3 API SPECIFICATION

    # Input  { self   => { type => 'object|string' },
    #          method => { type => 'string' } }
    # Output { type => 'coderef|undef' }

=head3 MESSAGES

    (none)

=cut

sub can
{
	my ($self, $method) = @_;

	# Premise: 'new' belongs to the wrapper, not to the inner object.
	# Conclusion: short-circuit before any object check is needed.
	return \&new if $method eq 'new';

	# Premise: if $self is not a ref (class-level call) OR the inner object
	#          has been freed (global destruction), there is no object to delegate to.
	# Conclusion: fall back to UNIVERSAL for what this package directly provides.
	return $self->SUPER::can($method)
		if !ref($self) || !ref($self->{object});

	# Premise: $self->{object} is alive and is a valid reference (Invariant I4).
	# Conclusion: delegate to the inner object first; fall back to UNIVERSAL.
	return $self->{object}->can($method) // $self->SUPER::can($method);
}

=head2 isa

Test class membership, delegating to the inner object's class
hierarchy when needed.  Overrides C<UNIVERSAL::isa> to support the
transparent decorator pattern.

=head3 Returns

True if the wrapper or its inner object is-a C<$class>.

=head3 EXAMPLE

    $cached->isa('My::Domain::Object');   # true if inner object is

=head3 API SPECIFICATION

    # Input  { self  => { type => 'object|string' },
    #          class => { type => 'string' } }
    # Output { type => 'bool' }

=head3 MESSAGES

    (none)

=cut

sub isa
{
	my ($self, $class) = @_;

	# Fast-path guards that do not require examining the inner object.
	#
	# Premise 1: $class eq ref($self) is logically subsumed by SUPER::isa,
	#   which also returns true for an exact class match -- but the string
	#   equality check is O(1) and avoids the UNIVERSAL dispatch overhead.
	#   Keeping it as a fast path is a valid micro-optimisation, NOT dead code.
	# Premise 2: $class eq __PACKAGE__ handles the subclass case:
	#   a My::Cached instance asked isa('Class::Simple::Readonly::Cached').
	# Premise 3: $class eq 'Class::Simple' is required because @ISA is
	#   intentionally empty; SUPER::isa would return false without this.
	# Premise 4: SUPER::isa covers the full UNIVERSAL hierarchy.
	# Conclusion: any of these makes the wrapper itself a member of $class.
	return 1 if $class eq ref($self)
	          || $class eq __PACKAGE__
	          || $class eq 'Class::Simple'
	          || $self->SUPER::isa($class);

	# Premise: none of the wrapper-level checks matched.
	# Premise: $self->{object} may be freed during global destruction; guard
	#          with ref() before delegating.
	# Conclusion: isa is true iff the inner object claims it.
	return !!(ref($self) && ref($self->{object}) && $self->{object}->isa($class));
}

# _build_cache_accessors -- install backend-specific _get/_set closures on $self.
# The cache backend (HASH vs CHI) is fixed for a wrapper's lifetime.



( run in 2.769 seconds using v1.01-cache-2.11-cpan-14f38c9f855 )